about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-12-25 07:20:48 -0500
committerNiko Matsakis <niko@alum.mit.edu>2014-12-30 09:34:38 -0500
commitf95bb55a1c4cb258ac8e6adde99cf1aadc5d776b (patch)
tree1d51732773bc60cfb8eadce4e51d3aecaf0714d1
parent771dd54ea6c09ac32093a46a0d9ed80502ce3b02 (diff)
downloadrust-f95bb55a1c4cb258ac8e6adde99cf1aadc5d776b.tar.gz
rust-f95bb55a1c4cb258ac8e6adde99cf1aadc5d776b.zip
Move the scalar types out of static data so that we can put `Rc` into sty.
-rw-r--r--src/librustc/metadata/tydecode.rs63
-rw-r--r--src/librustc/middle/astconv_util.rs10
-rw-r--r--src/librustc/middle/infer/combine.rs14
-rw-r--r--src/librustc/middle/infer/mod.rs8
-rw-r--r--src/librustc/middle/infer/resolve.rs6
-rw-r--r--src/librustc/middle/infer/sub.rs2
-rw-r--r--src/librustc/middle/infer/unify.rs14
-rw-r--r--src/librustc/middle/intrinsicck.rs4
-rw-r--r--src/librustc/middle/mem_categorization.rs8
-rw-r--r--src/librustc/middle/traits/select.rs5
-rw-r--r--src/librustc/middle/ty.rs165
-rw-r--r--src/librustc_driver/test.rs103
-rw-r--r--src/librustc_trans/trans/_match.rs2
-rw-r--r--src/librustc_trans/trans/adt.rs29
-rw-r--r--src/librustc_trans/trans/base.rs4
-rw-r--r--src/librustc_trans/trans/cleanup.rs2
-rw-r--r--src/librustc_trans/trans/closure.rs4
-rw-r--r--src/librustc_trans/trans/debuginfo.rs13
-rw-r--r--src/librustc_trans/trans/glue.rs6
-rw-r--r--src/librustc_typeck/astconv.rs8
-rw-r--r--src/librustc_typeck/check/_match.rs22
-rw-r--r--src/librustc_typeck/check/method/confirm.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs342
-rw-r--r--src/librustc_typeck/check/vtable.rs3
-rw-r--r--src/librustc_typeck/check/writeback.rs4
-rw-r--r--src/librustc_typeck/collect.rs2
-rw-r--r--src/librustc_typeck/lib.rs8
27 files changed, 464 insertions, 391 deletions
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 9b008f36a96..01cde5138c5 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -384,39 +384,40 @@ fn parse_trait_ref<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
 }
 
 fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
+    let tcx = st.tcx;
     match next(st) {
-      'b' => return ty::mk_bool(),
-      'i' => return ty::mk_int(),
-      'u' => return ty::mk_uint(),
+      'b' => return tcx.types.bool,
+      'i' => return tcx.types.int,
+      'u' => return tcx.types.uint,
       'M' => {
         match next(st) {
-          'b' => return ty::mk_mach_uint(ast::TyU8),
-          'w' => return ty::mk_mach_uint(ast::TyU16),
-          'l' => return ty::mk_mach_uint(ast::TyU32),
-          'd' => return ty::mk_mach_uint(ast::TyU64),
-          'B' => return ty::mk_mach_int(ast::TyI8),
-          'W' => return ty::mk_mach_int(ast::TyI16),
-          'L' => return ty::mk_mach_int(ast::TyI32),
-          'D' => return ty::mk_mach_int(ast::TyI64),
-          'f' => return ty::mk_mach_float(ast::TyF32),
-          'F' => return ty::mk_mach_float(ast::TyF64),
+          'b' => return tcx.types.u8,
+          'w' => return tcx.types.u16,
+          'l' => return tcx.types.u32,
+          'd' => return tcx.types.u64,
+          'B' => return tcx.types.i8,
+          'W' => return tcx.types.i16,
+          'L' => return tcx.types.i32,
+          'D' => return tcx.types.i64,
+          'f' => return tcx.types.f32,
+          'F' => return tcx.types.f64,
           _ => panic!("parse_ty: bad numeric type")
         }
       }
-      'c' => return ty::mk_char(),
+      'c' => return tcx.types.char,
       't' => {
         assert_eq!(next(st), '[');
         let def = parse_def(st, NominalType, |x,y| conv(x,y));
         let substs = parse_substs(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
-        return ty::mk_enum(st.tcx, def, st.tcx.mk_substs(substs));
+        return ty::mk_enum(tcx, def, st.tcx.mk_substs(substs));
       }
       'x' => {
         assert_eq!(next(st), '[');
         let trait_ref = ty::Binder(parse_trait_ref(st, |x,y| conv(x,y)));
         let bounds = parse_existential_bounds(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
-        return ty::mk_trait(st.tcx, trait_ref, bounds);
+        return ty::mk_trait(tcx, trait_ref, bounds);
       }
       'p' => {
         let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
@@ -425,41 +426,41 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
         assert_eq!(next(st), '|');
         let space = parse_param_space(st);
         assert_eq!(next(st), '|');
-        return ty::mk_param(st.tcx, space, index, did);
+        return ty::mk_param(tcx, space, index, did);
       }
-      '~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| conv(x,y))),
-      '*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))),
+      '~' => return ty::mk_uniq(tcx, parse_ty(st, |x,y| conv(x,y))),
+      '*' => return ty::mk_ptr(tcx, parse_mt(st, |x,y| conv(x,y))),
       '&' => {
         let r = parse_region(st, |x,y| conv(x,y));
         let mt = parse_mt(st, |x,y| conv(x,y));
-        return ty::mk_rptr(st.tcx, st.tcx.mk_region(r), mt);
+        return ty::mk_rptr(tcx, tcx.mk_region(r), mt);
       }
       'V' => {
         let t = parse_ty(st, |x,y| conv(x,y));
         let sz = parse_size(st);
-        return ty::mk_vec(st.tcx, t, sz);
+        return ty::mk_vec(tcx, t, sz);
       }
       'v' => {
-        return ty::mk_str(st.tcx);
+        return ty::mk_str(tcx);
       }
       'T' => {
         assert_eq!(next(st), '[');
         let mut params = Vec::new();
         while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
         st.pos = st.pos + 1u;
-        return ty::mk_tup(st.tcx, params);
+        return ty::mk_tup(tcx, params);
       }
       'f' => {
-        return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y)));
+        return ty::mk_closure(tcx, parse_closure_ty(st, |x,y| conv(x,y)));
       }
       'F' => {
           let def_id = parse_def(st, NominalType, |x,y| conv(x,y));
-          return ty::mk_bare_fn(st.tcx, Some(def_id),
-                                st.tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y))));
+          return ty::mk_bare_fn(tcx, Some(def_id),
+                                tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y))));
       }
       'G' => {
-          return ty::mk_bare_fn(st.tcx, None,
-                                st.tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y))));
+          return ty::mk_bare_fn(tcx, None,
+                                tcx.mk_bare_fn(parse_bare_fn_ty(st, |x,y| conv(x,y))));
       }
       '#' => {
         let pos = parse_hex(st);
@@ -470,7 +471,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
                                          pos: pos,
                                          len: len };
 
-        match st.tcx.rcache.borrow().get(&key).cloned() {
+        match tcx.rcache.borrow().get(&key).cloned() {
           Some(tt) => return tt,
           None => {}
         }
@@ -479,7 +480,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
             .. *st
         };
         let tt = parse_ty(&mut ps, |x,y| conv(x,y));
-        st.tcx.rcache.borrow_mut().insert(key, tt);
+        tcx.rcache.borrow_mut().insert(key, tt);
         return tt;
       }
       '\"' => {
@@ -504,7 +505,7 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> {
                   st.tcx.mk_region(region), st.tcx.mk_substs(substs));
       }
       'e' => {
-          return ty::mk_err();
+          return tcx.types.err;
       }
       c => { panic!("unexpected char in type string: {}", c);}
     }
diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs
index 060e2f67faf..b1b4fd831a0 100644
--- a/src/librustc/middle/astconv_util.rs
+++ b/src/librustc/middle/astconv_util.rs
@@ -57,23 +57,23 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
                     match nty {
                         ast::TyBool => {
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_bool())
+                            Some(tcx.types.bool)
                         }
                         ast::TyChar => {
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_char())
+                            Some(tcx.types.char)
                         }
                         ast::TyInt(it) => {
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_int(it))
+                            Some(ty::mk_mach_int(tcx, it))
                         }
                         ast::TyUint(uit) => {
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_uint(uit))
+                            Some(ty::mk_mach_uint(tcx, uit))
                         }
                         ast::TyFloat(ft) => {
                             check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_float(ft))
+                            Some(ty::mk_mach_float(tcx, ft))
                         }
                         ast::TyStr => {
                             Some(ty::mk_str(tcx))
diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs
index 04ae0a5a604..9f5eca142c3 100644
--- a/src/librustc/middle/infer/combine.rs
+++ b/src/librustc/middle/infer/combine.rs
@@ -397,8 +397,8 @@ pub fn expected_found<'tcx, C: Combine<'tcx>, T>(
 pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
                                          a: Ty<'tcx>,
                                          b: Ty<'tcx>)
-                                         -> cres<'tcx, Ty<'tcx>> {
-
+                                         -> cres<'tcx, Ty<'tcx>>
+{
     let tcx = this.infcx().tcx;
     let a_sty = &a.sty;
     let b_sty = &b.sty;
@@ -415,7 +415,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
       }
 
       (&ty::ty_err, _) | (_, &ty::ty_err) => {
-          Ok(ty::mk_err())
+          Ok(tcx.types.err)
       }
 
         // Relate integral variables to other types
@@ -592,8 +592,8 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
     {
         try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
         match val {
-            IntType(v) => Ok(ty::mk_mach_int(v)),
-            UintType(v) => Ok(ty::mk_mach_uint(v))
+            IntType(v) => Ok(ty::mk_mach_int(this.tcx(), v)),
+            UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v))
         }
     }
 
@@ -604,7 +604,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
         val: ast::FloatTy) -> cres<'tcx, Ty<'tcx>>
     {
         try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
-        Ok(ty::mk_mach_float(val))
+        Ok(ty::mk_mach_float(this.tcx(), val))
     }
 }
 
@@ -763,7 +763,7 @@ impl<'cx, 'tcx> ty_fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> {
             ty::ty_infer(ty::TyVar(vid)) => {
                 if vid == self.for_vid {
                     self.cycle_detected = true;
-                    ty::mk_err()
+                    self.tcx().types.err
                 } else {
                     match self.infcx.type_variables.borrow().probe(vid) {
                         Some(u) => self.fold_ty(u),
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index 07823779216..2231c0088e7 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -324,7 +324,7 @@ pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
         Ok(t) => t,
         Err(ref err) => {
             cx.report_and_explain_type_error(trace, err);
-            ty::mk_err()
+            cx.tcx.types.err
         }
     }
 }
@@ -1058,12 +1058,12 @@ impl<'tcx> TypeTrace<'tcx> {
         self.origin.span()
     }
 
-    pub fn dummy() -> TypeTrace<'tcx> {
+    pub fn dummy(tcx: &ty::ctxt<'tcx>) -> TypeTrace<'tcx> {
         TypeTrace {
             origin: Misc(codemap::DUMMY_SP),
             values: Types(ty::expected_found {
-                expected: ty::mk_err(),
-                found: ty::mk_err(),
+                expected: tcx.types.err,
+                found: tcx.types.err,
             })
         }
     }
diff --git a/src/librustc/middle/infer/resolve.rs b/src/librustc/middle/infer/resolve.rs
index 12400de31ed..ca2ae25e6c6 100644
--- a/src/librustc/middle/infer/resolve.rs
+++ b/src/librustc/middle/infer/resolve.rs
@@ -83,15 +83,15 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
             match t.sty {
                 ty::ty_infer(ty::TyVar(vid)) => {
                     self.err = Some(unresolved_ty(vid));
-                    ty::mk_err()
+                    self.tcx().types.err
                 }
                 ty::ty_infer(ty::IntVar(vid)) => {
                     self.err = Some(unresolved_int_ty(vid));
-                    ty::mk_err()
+                    self.tcx().types.err
                 }
                 ty::ty_infer(ty::FloatVar(vid)) => {
                     self.err = Some(unresolved_float_ty(vid));
-                    ty::mk_err()
+                    self.tcx().types.err
                 }
                 ty::ty_infer(_) => {
                     self.infcx.tcx.sess.bug(
diff --git a/src/librustc/middle/infer/sub.rs b/src/librustc/middle/infer/sub.rs
index 2b8adfb7c1e..4bd3308728c 100644
--- a/src/librustc/middle/infer/sub.rs
+++ b/src/librustc/middle/infer/sub.rs
@@ -146,7 +146,7 @@ impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> {
             }
 
             (&ty::ty_err, _) | (_, &ty::ty_err) => {
-                Ok(ty::mk_err())
+                Ok(self.tcx().types.err)
             }
 
             _ => {
diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs
index dcf70263c0a..3127ef5d8a5 100644
--- a/src/librustc/middle/infer/unify.rs
+++ b/src/librustc/middle/infer/unify.rs
@@ -225,7 +225,7 @@ impl<K,V> sv::SnapshotVecDelegate<VarValue<K,V>,()> for Delegate {
 /// Indicates a type that does not have any kind of subtyping
 /// relationship.
 pub trait SimplyUnifiable<'tcx> : Clone + PartialEq + Repr<'tcx> {
-    fn to_type(&self) -> Ty<'tcx>;
+    fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
     fn to_type_err(expected_found<Self>) -> ty::type_err<'tcx>;
 }
 
@@ -337,7 +337,7 @@ impl<'a,'tcx,V:SimplyUnifiable<'tcx>,K:UnifyKey<'tcx, Option<V>>>
         let node_a = table.borrow_mut().get(tcx, a_id);
         match node_a.value {
             None => None,
-            Some(ref a_t) => Some(a_t.to_type())
+            Some(ref a_t) => Some(a_t.to_type(tcx))
         }
     }
 }
@@ -363,10 +363,10 @@ impl<'tcx> UnifyKey<'tcx, Option<IntVarValue>> for ty::IntVid {
 }
 
 impl<'tcx> SimplyUnifiable<'tcx> for IntVarValue {
-    fn to_type(&self) -> Ty<'tcx> {
+    fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
         match *self {
-            ty::IntType(i) => ty::mk_mach_int(i),
-            ty::UintType(i) => ty::mk_mach_uint(i),
+            ty::IntType(i) => ty::mk_mach_int(tcx, i),
+            ty::UintType(i) => ty::mk_mach_uint(tcx, i),
         }
     }
 
@@ -399,8 +399,8 @@ impl<'tcx> UnifyValue<'tcx> for Option<ast::FloatTy> {
 }
 
 impl<'tcx> SimplyUnifiable<'tcx> for ast::FloatTy {
-    fn to_type(&self) -> Ty<'tcx> {
-        ty::mk_mach_float(*self)
+    fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
+        ty::mk_mach_float(tcx, *self)
     }
 
     fn to_type_err(err: expected_found<ast::FloatTy>) -> ty::type_err<'tcx> {
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 1f4ddd1a5d6..df06b3b7789 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -28,8 +28,8 @@ pub fn check_crate(tcx: &ctxt) {
     let mut visitor = IntrinsicCheckingVisitor {
         tcx: tcx,
         param_envs: Vec::new(),
-        dummy_sized_ty: ty::mk_int(),
-        dummy_unsized_ty: ty::mk_vec(tcx, ty::mk_int(), None),
+        dummy_sized_ty: tcx.types.int,
+        dummy_unsized_ty: ty::mk_vec(tcx, tcx.types.int, None),
     };
     visit::walk_crate(&mut visitor, tcx.map.krate());
 }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 5d3134b9629..c15001af68d 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -755,7 +755,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                         // instead of bothering to construct a proper
                         // one.
                         base.mutbl = McImmutable;
-                        base.ty = ty::mk_err();
+                        base.ty = self.tcx().types.err;
                         Rc::new(cmt_ {
                             id: id,
                             span: span,
@@ -781,7 +781,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                         is_unboxed: is_unboxed
                     }),
                     mutbl: McImmutable,
-                    ty: ty::mk_err(),
+                    ty: self.tcx().types.err,
                     note: NoteNone
                 };
 
@@ -792,7 +792,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                             span: span,
                             cat: cat_deref(Rc::new(base), 0, env_ptr),
                             mutbl: env_mutbl,
-                            ty: ty::mk_err(),
+                            ty: self.tcx().types.err,
                             note: NoteClosureEnv(upvar_id)
                         };
                     }
@@ -987,7 +987,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                 ty::ty_fn_args(method_ty)[0]
             }
             None => {
-                match ty::array_element_ty(base_cmt.ty) {
+                match ty::array_element_ty(self.tcx(), base_cmt.ty) {
                     Some(ty) => ty,
                     None => {
                         self.tcx().sess.span_bug(
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 6b56bbac201..a22a602ddff 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -1100,8 +1100,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         } else {
                             // Recursively check all supertraits to find out if any further
                             // bounds are required and thus we must fulfill.
-                            let tmp_tr = data.principal_trait_ref_with_self_ty(self.tcx(),
-                                                                               ty::mk_err());
+                            let tmp_tr =
+                                data.principal_trait_ref_with_self_ty(self.tcx(),
+                                                                      self.tcx().types.err);
                             for tr in util::supertraits(self.tcx(), tmp_tr) {
                                 let td = ty::lookup_trait_def(self.tcx(), tr.def_id());
 
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index c082c12da5b..8a0e5ea0bb3 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -639,6 +639,24 @@ impl<'tcx> CtxtArenas<'tcx> {
     }
 }
 
+pub struct CommonTypes<'tcx> {
+    pub bool: Ty<'tcx>,
+    pub char: Ty<'tcx>,
+    pub int: Ty<'tcx>,
+    pub i8: Ty<'tcx>,
+    pub i16: Ty<'tcx>,
+    pub i32: Ty<'tcx>,
+    pub i64: Ty<'tcx>,
+    pub uint: Ty<'tcx>,
+    pub u8: Ty<'tcx>,
+    pub u16: Ty<'tcx>,
+    pub u32: Ty<'tcx>,
+    pub u64: Ty<'tcx>,
+    pub f32: Ty<'tcx>,
+    pub f64: Ty<'tcx>,
+    pub err: Ty<'tcx>,
+}
+
 /// The data structure to keep track of all the information that typechecker
 /// generates so that so that it can be reused and doesn't have to be redone
 /// later on.
@@ -651,11 +669,15 @@ pub struct ctxt<'tcx> {
     // FIXME(eddyb) use a FnvHashSet<InternedTy<'tcx>> when equivalent keys can
     // queried from a HashSet.
     interner: RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
+
     // FIXME as above, use a hashset if equivalent elements can be queried.
     substs_interner: RefCell<FnvHashMap<&'tcx Substs<'tcx>, &'tcx Substs<'tcx>>>,
     bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>,
     region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>,
 
+    /// Common types, pre-interned for your convenience.
+    pub types: CommonTypes<'tcx>,
+
     pub sess: Session,
     pub def_map: DefMap,
 
@@ -1297,54 +1319,6 @@ pub enum BoundRegion {
     BrEnv
 }
 
-#[inline]
-pub fn mk_prim_t<'tcx>(primitive: &'tcx TyS<'static>) -> Ty<'tcx> {
-    // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
-    unsafe { &*(primitive as *const _ as *const TyS<'tcx>) }
-}
-
-// Do not change these from static to const, interning types requires
-// the primitives to have a significant address.
-macro_rules! def_prim_tys {
-    ($($name:ident -> $sty:expr;)*) => (
-        $(#[inline] pub fn $name<'tcx>() -> Ty<'tcx> {
-            static PRIM_TY: TyS<'static> = TyS {
-                sty: $sty,
-                flags: NO_TYPE_FLAGS,
-                region_depth: 0,
-            };
-            mk_prim_t(&PRIM_TY)
-        })*
-    )
-}
-
-def_prim_tys!{
-    mk_bool ->  ty_bool;
-    mk_char ->  ty_char;
-    mk_int ->   ty_int(ast::TyI);
-    mk_i8 ->    ty_int(ast::TyI8);
-    mk_i16 ->   ty_int(ast::TyI16);
-    mk_i32 ->   ty_int(ast::TyI32);
-    mk_i64 ->   ty_int(ast::TyI64);
-    mk_uint ->  ty_uint(ast::TyU);
-    mk_u8 ->    ty_uint(ast::TyU8);
-    mk_u16 ->   ty_uint(ast::TyU16);
-    mk_u32 ->   ty_uint(ast::TyU32);
-    mk_u64 ->   ty_uint(ast::TyU64);
-    mk_f32 ->   ty_float(ast::TyF32);
-    mk_f64 ->   ty_float(ast::TyF64);
-}
-
-#[inline]
-pub fn mk_err<'tcx>() -> Ty<'tcx> {
-    static TY_ERR: TyS<'static> = TyS {
-        sty: ty_err,
-        flags: HAS_TY_ERR,
-        region_depth: 0,
-    };
-    mk_prim_t(&TY_ERR)
-}
-
 // NB: If you change this, you'll probably want to change the corresponding
 // AST structure in libsyntax/ast.rs as well.
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
@@ -2102,6 +2076,31 @@ impl UnboxedClosureKind {
     }
 }
 
+impl<'tcx> CommonTypes<'tcx> {
+    fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
+           interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>)
+           -> CommonTypes<'tcx>
+    {
+        CommonTypes {
+            bool: intern_ty(arena, interner, ty_bool),
+            char: intern_ty(arena, interner, ty_char),
+            err: intern_ty(arena, interner, ty_err),
+            int: intern_ty(arena, interner, ty_int(ast::TyI)),
+            i8: intern_ty(arena, interner, ty_int(ast::TyI8)),
+            i16: intern_ty(arena, interner, ty_int(ast::TyI16)),
+            i32: intern_ty(arena, interner, ty_int(ast::TyI32)),
+            i64: intern_ty(arena, interner, ty_int(ast::TyI64)),
+            uint: intern_ty(arena, interner, ty_uint(ast::TyU)),
+            u8: intern_ty(arena, interner, ty_uint(ast::TyU8)),
+            u16: intern_ty(arena, interner, ty_uint(ast::TyU16)),
+            u32: intern_ty(arena, interner, ty_uint(ast::TyU32)),
+            u64: intern_ty(arena, interner, ty_uint(ast::TyU64)),
+            f32: intern_ty(arena, interner, ty_float(ast::TyF32)),
+            f64: intern_ty(arena, interner, ty_float(ast::TyF64)),
+        }
+    }
+}
+
 pub fn mk_ctxt<'tcx>(s: Session,
                      arenas: &'tcx CtxtArenas<'tcx>,
                      dm: DefMap,
@@ -2111,13 +2110,18 @@ pub fn mk_ctxt<'tcx>(s: Session,
                      capture_modes: RefCell<CaptureModeMap>,
                      region_maps: middle::region::RegionMaps,
                      lang_items: middle::lang_items::LanguageItems,
-                     stability: stability::Index) -> ctxt<'tcx> {
+                     stability: stability::Index) -> ctxt<'tcx>
+{
+    let mut interner = FnvHashMap::new();
+    let common_types = CommonTypes::new(&arenas.type_, &mut interner);
+
     ctxt {
         arenas: arenas,
         interner: RefCell::new(FnvHashMap::new()),
         substs_interner: RefCell::new(FnvHashMap::new()),
         bare_fn_interner: RefCell::new(FnvHashMap::new()),
         region_interner: RefCell::new(FnvHashMap::new()),
+        types: common_types,
         named_region_map: named_region_map,
         item_variance_map: RefCell::new(DefIdMap::new()),
         variance_computed: Cell::new(false),
@@ -2212,31 +2216,32 @@ impl<'tcx> ctxt<'tcx> {
 // 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: sty<'tcx>) -> Ty<'tcx> {
-    // Check for primitive types.
-    match st {
-        ty_err => return mk_err(),
-        ty_bool => return mk_bool(),
-        ty_int(i) => return mk_mach_int(i),
-        ty_uint(u) => return mk_mach_uint(u),
-        ty_float(f) => return mk_mach_float(f),
-        ty_char => return mk_char(),
-        _ => {}
-    };
+    let mut interner = cx.interner.borrow_mut();
+    intern_ty(cx.type_arena, &mut *interner, st)
+}
 
-    match cx.interner.borrow().get(&st) {
+fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>,
+                   interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>,
+                   st: sty<'tcx>)
+                   -> Ty<'tcx>
+{
+    match interner.get(&st) {
         Some(ty) => return *ty,
         _ => ()
     }
 
     let flags = FlagComputation::for_sty(&st);
 
-    let ty = cx.arenas.type_.alloc(TyS {
+    let ty = type_arena.alloc(TyS {
         sty: st,
         flags: flags.flags,
         region_depth: flags.depth,
     });
 
-    cx.interner.borrow_mut().insert(InternedTy { ty: ty }, ty);
+    debug!("Interned type: {} Pointer: {}",
+           ty, ty as *const _);
+
+    interner.insert(InternedTy { ty: ty }, ty);
 
     ty
 }
@@ -2416,30 +2421,30 @@ impl FlagComputation {
     }
 }
 
-pub fn mk_mach_int<'tcx>(tm: ast::IntTy) -> Ty<'tcx> {
+pub fn mk_mach_int<'tcx>(tcx: &ctxt<'tcx>, tm: ast::IntTy) -> Ty<'tcx> {
     match tm {
-        ast::TyI    => mk_int(),
-        ast::TyI8   => mk_i8(),
-        ast::TyI16  => mk_i16(),
-        ast::TyI32  => mk_i32(),
-        ast::TyI64  => mk_i64(),
+        ast::TyI    => tcx.types.int,
+        ast::TyI8   => tcx.types.i8,
+        ast::TyI16  => tcx.types.i16,
+        ast::TyI32  => tcx.types.i32,
+        ast::TyI64  => tcx.types.i64,
     }
 }
 
-pub fn mk_mach_uint<'tcx>(tm: ast::UintTy) -> Ty<'tcx> {
+pub fn mk_mach_uint<'tcx>(tcx: &ctxt<'tcx>, tm: ast::UintTy) -> Ty<'tcx> {
     match tm {
-        ast::TyU    => mk_uint(),
-        ast::TyU8   => mk_u8(),
-        ast::TyU16  => mk_u16(),
-        ast::TyU32  => mk_u32(),
-        ast::TyU64  => mk_u64(),
+        ast::TyU    => tcx.types.uint,
+        ast::TyU8   => tcx.types.u8,
+        ast::TyU16  => tcx.types.u16,
+        ast::TyU32  => tcx.types.u32,
+        ast::TyU64  => tcx.types.u64,
     }
 }
 
-pub fn mk_mach_float<'tcx>(tm: ast::FloatTy) -> Ty<'tcx> {
+pub fn mk_mach_float<'tcx>(tcx: &ctxt<'tcx>, tm: ast::FloatTy) -> Ty<'tcx> {
     match tm {
-        ast::TyF32  => mk_f32(),
-        ast::TyF64  => mk_f64(),
+        ast::TyF32  => tcx.types.f32,
+        ast::TyF64  => tcx.types.f64,
     }
 }
 
@@ -2769,7 +2774,7 @@ pub fn type_is_simd(cx: &ctxt, ty: Ty) -> bool {
 pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.sty {
         ty_vec(ty, _) => ty,
-        ty_str => mk_mach_uint(ast::TyU8),
+        ty_str => mk_mach_uint(cx, ast::TyU8),
         ty_open(ty) => sequence_element_type(cx, ty),
         _ => cx.sess.bug(format!("sequence_element_type called on non-sequence value: {}",
                                  ty_to_string(cx, ty))[]),
@@ -3760,10 +3765,10 @@ pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
 // 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>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
+pub fn array_element_ty<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
     match ty.sty {
         ty_vec(ty, _) => Some(ty),
-        ty_str => Some(mk_u8()),
+        ty_str => Some(tcx.types.u8),
         _ => None
     }
 }
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 941155ac5e7..6329acfb578 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -28,7 +28,7 @@ use rustc_typeck::middle::infer::glb::Glb;
 use rustc_typeck::middle::infer::sub::Sub;
 use rustc_typeck::util::ppaux::{ty_to_string, Repr, UserString};
 use rustc::session::{mod,config};
-use syntax::{abi, ast, ast_map, ast_util};
+use syntax::{abi, ast, ast_map};
 use syntax::codemap;
 use syntax::codemap::{Span, CodeMap, DUMMY_SP};
 use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, Help};
@@ -145,6 +145,10 @@ fn test_env<F>(source_string: &str,
 }
 
 impl<'a, 'tcx> Env<'a, 'tcx> {
+    pub fn tcx(&self) -> &ty::ctxt<'tcx> {
+        self.infcx.tcx
+    }
+
     pub fn create_region_hierarchy(&self, rh: &RH) {
         for child_rh in rh.sub.iter() {
             self.create_region_hierarchy(child_rh);
@@ -296,7 +300,8 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     }
 
     pub fn t_param(&self, space: subst::ParamSpace, index: u32) -> Ty<'tcx> {
-        ty::mk_param(self.infcx.tcx, space, index, ast_util::local_def(ast::DUMMY_NODE_ID))
+        let name = format!("T{}", index);
+        ty::mk_param(self.infcx.tcx, space, index, token::intern(name[]))
     }
 
     pub fn re_early_bound(&self,
@@ -314,14 +319,16 @@ 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), ty::mk_int())
+        ty::mk_imm_rptr(self.infcx.tcx,
+                        self.infcx.tcx.mk_region(r),
+                        self.tcx().types.int)
     }
 
     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),
-                        ty::mk_int())
+                        self.tcx().types.int)
     }
 
     pub fn t_rptr_late_bound_with_debruijn(&self,
@@ -331,12 +338,13 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         let r = self.re_late_bound_with_debruijn(id, debruijn);
         ty::mk_imm_rptr(self.infcx.tcx,
                         self.infcx.tcx.mk_region(r),
-                        ty::mk_int())
+                        self.tcx().types.int)
     }
 
     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), ty::mk_int())
+        ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r),
+                        self.tcx().types.int)
     }
 
     pub fn re_free(&self, nid: ast::NodeId, id: u32) -> ty::Region {
@@ -346,15 +354,19 @@ 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), ty::mk_int())
+        ty::mk_imm_rptr(self.infcx.tcx,
+                        self.infcx.tcx.mk_region(r),
+                        self.tcx().types.int)
     }
 
     pub fn t_rptr_static(&self) -> Ty<'tcx> {
-        ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(ty::ReStatic), ty::mk_int())
+        ty::mk_imm_rptr(self.infcx.tcx,
+                        self.infcx.tcx.mk_region(ty::ReStatic),
+                        self.tcx().types.int)
     }
 
     pub fn dummy_type_trace(&self) -> infer::TypeTrace<'tcx> {
-        infer::TypeTrace::dummy()
+        infer::TypeTrace::dummy(self.tcx())
     }
 
     pub fn sub(&self) -> Sub<'a, 'tcx> {
@@ -480,8 +492,8 @@ fn sub_free_bound_false() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_free1 = env.t_rptr_free(0, 1);
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
-        env.check_not_sub(env.t_fn(&[t_rptr_free1], ty::mk_int()),
-                          env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_not_sub(env.t_fn(&[t_rptr_free1], env.tcx().types.int),
+                          env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -496,8 +508,8 @@ fn sub_bound_free_true() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_free1 = env.t_rptr_free(0, 1);
-        env.check_sub(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free1], ty::mk_int()));
+        env.check_sub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free1], env.tcx().types.int));
     })
 }
 
@@ -512,8 +524,8 @@ fn sub_free_bound_false_infer() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_infer1 = env.infcx.next_ty_var();
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
-        env.check_not_sub(env.t_fn(&[t_infer1], ty::mk_int()),
-                          env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_not_sub(env.t_fn(&[t_infer1], env.tcx().types.int),
+                          env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -531,9 +543,9 @@ fn lub_free_bound_infer() {
         let t_infer1 = env.infcx.next_ty_var();
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_free1 = env.t_rptr_free(0, 1);
-        env.check_lub(env.t_fn(&[t_infer1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free1], ty::mk_int()));
+        env.check_lub(env.t_fn(&[t_infer1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free1], env.tcx().types.int));
     });
 }
 
@@ -542,9 +554,9 @@ fn lub_bound_bound() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_bound2 = env.t_rptr_late_bound(2);
-        env.check_lub(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound2], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound2], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -553,9 +565,9 @@ fn lub_bound_free() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_free1 = env.t_rptr_free(0, 1);
-        env.check_lub(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free1], ty::mk_int()));
+        env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free1], env.tcx().types.int));
     })
 }
 
@@ -564,9 +576,9 @@ fn lub_bound_static() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_static = env.t_rptr_static();
-        env.check_lub(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_static], ty::mk_int()),
-                      env.t_fn(&[t_rptr_static], ty::mk_int()));
+        env.check_lub(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_static], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_static], env.tcx().types.int));
     })
 }
 
@@ -587,9 +599,9 @@ fn lub_free_free() {
         let t_rptr_free1 = env.t_rptr_free(0, 1);
         let t_rptr_free2 = env.t_rptr_free(0, 2);
         let t_rptr_static = env.t_rptr_static();
-        env.check_lub(env.t_fn(&[t_rptr_free1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free2], ty::mk_int()),
-                      env.t_fn(&[t_rptr_static], ty::mk_int()));
+        env.check_lub(env.t_fn(&[t_rptr_free1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free2], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_static], env.tcx().types.int));
     })
 }
 
@@ -612,9 +624,9 @@ fn glb_free_free_with_common_scope() {
         let t_rptr_free1 = env.t_rptr_free(0, 1);
         let t_rptr_free2 = env.t_rptr_free(0, 2);
         let t_rptr_scope = env.t_rptr_scope(0);
-        env.check_glb(env.t_fn(&[t_rptr_free1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free2], ty::mk_int()),
-                      env.t_fn(&[t_rptr_scope], ty::mk_int()));
+        env.check_glb(env.t_fn(&[t_rptr_free1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free2], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_scope], env.tcx().types.int));
     })
 }
 
@@ -623,9 +635,9 @@ fn glb_bound_bound() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_bound2 = env.t_rptr_late_bound(2);
-        env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound2], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound2], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -634,9 +646,9 @@ fn glb_bound_free() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_free1 = env.t_rptr_free(0, 1);
-        env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_free1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_free1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -648,9 +660,9 @@ fn glb_bound_free_infer() {
 
         // compute GLB(fn(_) -> int, for<'b> fn(&'b int) -> int),
         // which should yield for<'b> fn(&'b int) -> int
-        env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_infer1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_infer1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
 
         // as a side-effect, computing GLB should unify `_` with
         // `&'_ int`
@@ -667,9 +679,9 @@ fn glb_bound_static() {
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let t_rptr_bound1 = env.t_rptr_late_bound(1);
         let t_rptr_static = env.t_rptr_static();
-        env.check_glb(env.t_fn(&[t_rptr_bound1], ty::mk_int()),
-                      env.t_fn(&[t_rptr_static], ty::mk_int()),
-                      env.t_fn(&[t_rptr_bound1], ty::mk_int()));
+        env.check_glb(env.t_fn(&[t_rptr_bound1], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_static], env.tcx().types.int),
+                      env.t_fn(&[t_rptr_bound1], env.tcx().types.int));
     })
 }
 
@@ -790,7 +802,6 @@ fn escaping() {
 /// late-bound region.
 #[test]
 fn subst_region_renumber_region() {
-
     test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
         let re_bound1 = env.re_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1));
 
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index db053686935..0e37cd0f3b8 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -1122,7 +1122,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                     let t = if kind == Compare {
                         left_ty
                     } else {
-                        ty::mk_uint() // vector length
+                        tcx.types.uint // vector length
                     };
                     let Result { bcx: after_cx, val: matches } = {
                         match opt.trans(bcx) {
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index 717c2af2beb..d01047c53b9 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -163,7 +163,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }).collect::<Vec<_>>();
             let packed = ty::lookup_packed(cx.tcx(), def_id);
             let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag();
-            if dtor { ftys.push(ty::mk_bool()); }
+            if dtor { ftys.push(cx.tcx().types.bool); }
 
             Univariant(mk_struct(cx, ftys[], packed, t), dtor)
         }
@@ -183,7 +183,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 // Uninhabitable; represent as unit
                 // (Typechecking will reject discriminant-sizing attrs.)
                 assert_eq!(hint, attr::ReprAny);
-                let ftys = if dtor { vec!(ty::mk_bool()) } else { vec!() };
+                let ftys = if dtor { vec!(cx.tcx().types.bool) } else { vec!() };
                 return Univariant(mk_struct(cx, ftys[], false, t),
                                   dtor);
             }
@@ -215,7 +215,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 // (Typechecking will reject discriminant-sizing attrs.)
                 assert_eq!(hint, attr::ReprAny);
                 let mut ftys = cases[0].tys.clone();
-                if dtor { ftys.push(ty::mk_bool()); }
+                if dtor { ftys.push(cx.tcx().types.bool); }
                 return Univariant(mk_struct(cx, ftys[], false, t),
                                   dtor);
             }
@@ -261,9 +261,9 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // Create the set of structs that represent each variant
             // Use the minimum integer type we figured out above
             let fields : Vec<_> = cases.iter().map(|c| {
-                let mut ftys = vec!(ty_of_inttype(min_ity));
+                let mut ftys = vec!(ty_of_inttype(cx.tcx(), min_ity));
                 ftys.push_all(c.tys.as_slice());
-                if dtor { ftys.push(ty::mk_bool()); }
+                if dtor { ftys.push(cx.tcx().types.bool); }
                 mk_struct(cx, ftys.as_slice(), false, t)
             }).collect();
 
@@ -314,9 +314,9 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             };
 
             let fields : Vec<_> = cases.iter().map(|c| {
-                let mut ftys = vec!(ty_of_inttype(ity));
+                let mut ftys = vec!(ty_of_inttype(cx.tcx(), ity));
                 ftys.push_all(c.tys[]);
-                if dtor { ftys.push(ty::mk_bool()); }
+                if dtor { ftys.push(cx.tcx().types.bool); }
                 mk_struct(cx, ftys[], false, t)
             }).collect();
 
@@ -553,11 +553,10 @@ fn bounds_usable(cx: &CrateContext, ity: IntType, bounds: &IntBounds) -> bool {
     }
 }
 
-// FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
-pub fn ty_of_inttype<'tcx>(ity: IntType) -> Ty<'tcx> {
+pub fn ty_of_inttype<'tcx>(tcx: &ty::ctxt<'tcx>, ity: IntType) -> Ty<'tcx> {
     match ity {
-        attr::SignedInt(t) => ty::mk_mach_int(t),
-        attr::UnsignedInt(t) => ty::mk_mach_uint(t)
+        attr::SignedInt(t) => ty::mk_mach_int(tcx, t),
+        attr::UnsignedInt(t) => ty::mk_mach_uint(tcx, t)
     }
 }
 
@@ -995,8 +994,10 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
 
 /// Access the struct drop flag, if present.
 pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, val: ValueRef)
-                                       -> datum::DatumBlock<'blk, 'tcx, datum::Expr> {
-    let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), ty::mk_bool());
+                                       -> datum::DatumBlock<'blk, 'tcx, datum::Expr>
+{
+    let tcx = bcx.tcx();
+    let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), tcx.types.bool);
     match *r {
         Univariant(ref st, true) => {
             let flag_ptr = GEPi(bcx, val, &[0, st.fields.len() - 1]);
@@ -1006,7 +1007,7 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx
             let fcx = bcx.fcx;
             let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
             let scratch = unpack_datum!(bcx, datum::lvalue_scratch_datum(
-                bcx, ty::mk_bool(), "drop_flag", false,
+                bcx, tcx.types.bool, "drop_flag", false,
                 cleanup::CustomScope(custom_cleanup_scope), (), |_, bcx, _| bcx
             ));
             bcx = fold_variants(bcx, r, val, |variant_cx, st, value| {
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 397baac960d..e0a717d8073 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -786,7 +786,7 @@ pub fn iter_structural_ty<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                                     substs, f);
               }
               (_match::Switch, Some(lldiscrim_a)) => {
-                  cx = f(cx, lldiscrim_a, ty::mk_int());
+                  cx = f(cx, lldiscrim_a, cx.tcx().types.int);
                   let unr_cx = fcx.new_temp_block("enum-iter-unr");
                   Unreachable(unr_cx);
                   let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb,
@@ -1765,7 +1765,7 @@ pub fn build_return_block<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>,
                 retptr.erase_from_parent();
             }
 
-            let retval = if retty == ty::FnConverging(ty::mk_bool()) {
+            let retval = if retty == ty::FnConverging(fcx.ccx.tcx().types.bool) {
                 Trunc(ret_cx, retval, Type::i1(fcx.ccx))
             } else {
                 retval
diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs
index d02d6c1e872..b4deea4c72f 100644
--- a/src/librustc_trans/trans/cleanup.rs
+++ b/src/librustc_trans/trans/cleanup.rs
@@ -736,7 +736,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
                         let f = base::decl_cdecl_fn(self.ccx,
                                                     "rust_eh_personality",
                                                     fty,
-                                                    ty::mk_i32());
+                                                    self.ccx.tcx().types.i32);
                         *personality = Some(f);
                         f
                     }
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index 0ae9de8c891..ed3c820f2fa 100644
--- a/src/librustc_trans/trans/closure.rs
+++ b/src/librustc_trans/trans/closure.rs
@@ -133,8 +133,8 @@ pub fn mk_closure_tys<'tcx>(tcx: &ty::ctxt<'tcx>,
 }
 
 fn tuplify_box_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Ty<'tcx> {
-    let ptr = ty::mk_imm_ptr(tcx, ty::mk_i8());
-    ty::mk_tup(tcx, vec!(ty::mk_uint(), ty::mk_nil_ptr(tcx), ptr, ptr, t))
+    let ptr = ty::mk_imm_ptr(tcx, tcx.types.i8);
+    ty::mk_tup(tcx, vec!(tcx.types.uint, ty::mk_nil_ptr(tcx), ptr, ptr, t))
 }
 
 fn allocate_cbox<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
index 56c42c7afde..98f87b27385 100644
--- a/src/librustc_trans/trans/debuginfo.rs
+++ b/src/librustc_trans/trans/debuginfo.rs
@@ -2487,9 +2487,10 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
                 let (discriminant_size, discriminant_align) =
                     size_and_align_of(cx, discriminant_llvm_type);
-                let discriminant_base_type_metadata = type_metadata(cx,
-                                                                    adt::ty_of_inttype(inttype),
-                                                                    codemap::DUMMY_SP);
+                let discriminant_base_type_metadata =
+                    type_metadata(cx,
+                                  adt::ty_of_inttype(cx.tcx(), inttype),
+                                  codemap::DUMMY_SP);
                 let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
 
                 let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| {
@@ -2797,7 +2798,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         MemberDescription {
             name: "length".to_string(),
             llvm_type: member_llvm_types[1],
-            type_metadata: type_metadata(cx, ty::mk_uint(), span),
+            type_metadata: type_metadata(cx, cx.tcx().types.uint, span),
             offset: ComputedMemberOffset,
             flags: FLAGS_NONE
         },
@@ -2963,7 +2964,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
         // FIXME Can we do better than this for unsized vec/str fields?
         ty::ty_vec(typ, None) => fixed_vec_metadata(cx, unique_type_id, typ, 0, usage_site_span),
-        ty::ty_str => fixed_vec_metadata(cx, unique_type_id, ty::mk_i8(), 0, usage_site_span),
+        ty::ty_str => fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, 0, usage_site_span),
         ty::ty_trait(..) => {
             MetadataCreationResult::new(
                         trait_pointer_metadata(cx, t, None, unique_type_id),
@@ -2975,7 +2976,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)
                 }
                 ty::ty_str => {
-                    vec_slice_metadata(cx, t, ty::mk_u8(), unique_type_id, usage_site_span)
+                    vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span)
                 }
                 ty::ty_trait(..) => {
                     MetadataCreationResult::new(
diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs
index 31455920c10..ab5c670ef5a 100644
--- a/src/librustc_trans/trans/glue.rs
+++ b/src/librustc_trans/trans/glue.rs
@@ -85,7 +85,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         return t
     }
     if !type_needs_drop(tcx, t) {
-        return ty::mk_i8();
+        return tcx.types.i8;
     }
     match t.sty {
         ty::ty_uniq(typ) if !type_needs_drop(tcx, typ)
@@ -93,7 +93,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             let llty = sizing_type_of(ccx, typ);
             // `Box<ZeroSizeType>` does not allocate.
             if llsize_of_alloc(ccx, llty) == 0 {
-                ty::mk_i8()
+                tcx.types.i8
             } else {
                 t
             }
@@ -200,7 +200,7 @@ fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         Load(bcx, llval)
     };
     let drop_flag = unpack_datum!(bcx, adt::trans_drop_flag_ptr(bcx, &*repr, struct_data));
-    with_cond(bcx, load_ty(bcx, drop_flag.val, ty::mk_bool()), |cx| {
+    with_cond(bcx, load_ty(bcx, drop_flag.val, bcx.tcx().types.bool), |cx| {
         trans_struct_drop(cx, t, v0, dtor_did, class_did, substs)
     })
 }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 859cb88ea9a..0ba528ad030 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -932,7 +932,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                                                  trait_ref, bounds[])
                     }
                     Err(ErrorReported) => {
-                        ty::mk_err()
+                        this.tcx().types.err
                     }
                 }
             }
@@ -1046,7 +1046,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                                                           .unwrap()
                                                           .identifier)
                                                   .get())[]);
-                        ty::mk_err()
+                        this.tcx().types.err
                     }
                     def::DefAssociatedPath(typ, assoc_ident) => {
                         // FIXME(#19541): in both branches we should consider
@@ -1485,8 +1485,8 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
                                                         partitioned_bounds);
 
     match main_trait_bound {
-        None => ty::mk_err(),
-        Some(principal) => ty::mk_trait(this.tcx(), (*principal).clone(), bounds)
+        None => this.tcx().types.err,
+        Some(principal) => ty::mk_trait(this.tcx(), principal, bounds)
     }
 }
 
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 4fbae637800..dc77a1e782b 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -142,7 +142,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &**inner, inner_ty);
             } else {
                 fcx.write_error(pat.id);
-                check_pat(pcx, &**inner, ty::mk_err());
+                check_pat(pcx, &**inner, tcx.types.err);
             }
         }
         ast::PatRegion(ref inner) => {
@@ -162,7 +162,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 check_pat(pcx, &**inner, inner_ty);
             } else {
                 fcx.write_error(pat.id);
-                check_pat(pcx, &**inner, ty::mk_err());
+                check_pat(pcx, &**inner, tcx.types.err);
             }
         }
         ast::PatVec(ref before, ref slice, ref after) => {
@@ -285,11 +285,11 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         };
 
         if let Some(ref e) = arm.guard {
-            check_expr_has_type(fcx, &**e, ty::mk_bool());
+            check_expr_has_type(fcx, &**e, tcx.types.bool);
         }
 
         if ty::type_is_error(result_ty) || ty::type_is_error(bty) {
-            ty::mk_err()
+            tcx.types.err
         } else {
             let (origin, expected, found) = match match_src {
                 /* if-let construct without an else block */
@@ -339,7 +339,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
             fcx.write_error(pat.id);
 
             for field in fields.iter() {
-                check_pat(pcx, &*field.node.pat, ty::mk_err());
+                check_pat(pcx, &*field.node.pat, tcx.types.err);
             }
             return;
         },
@@ -358,7 +358,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
                     fcx.write_error(pat.id);
 
                     for field in fields.iter() {
-                        check_pat(pcx, &*field.node.pat, ty::mk_err());
+                        check_pat(pcx, &*field.node.pat, tcx.types.err);
                     }
                     return;
                 }
@@ -430,7 +430,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
 
             if let Some(ref subpats) = *subpats {
                 for pat in subpats.iter() {
-                    check_pat(pcx, &**pat, ty::mk_err());
+                    check_pat(pcx, &**pat, tcx.types.err);
                 }
             }
             return;
@@ -448,7 +448,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
                       subpats.len(), if subpats.len() == 1 {""} else {"s"}, kind_name);
 
             for pat in subpats.iter() {
-                check_pat(pcx, &**pat, ty::mk_err());
+                check_pat(pcx, &**pat, tcx.types.err);
             }
         } else {
             span_err!(tcx.sess, pat.span, E0023,
@@ -458,7 +458,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
                       arg_tys.len(), if arg_tys.len() == 1 {""} else {"s"});
 
             for pat in subpats.iter() {
-                check_pat(pcx, &**pat, ty::mk_err());
+                check_pat(pcx, &**pat, tcx.types.err);
             }
         }
     }
@@ -496,7 +496,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                 span_note!(tcx.sess, *occupied.get(),
                     "field `{}` previously bound here",
                     token::get_ident(field.ident));
-                ty::mk_err()
+                tcx.types.err
             }
             Vacant(vacant) => {
                 vacant.set(span);
@@ -506,7 +506,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                             "struct `{}` does not have a field named `{}`",
                             ty::item_path_str(tcx, struct_id),
                             token::get_ident(field.ident));
-                        ty::mk_err()
+                        tcx.types.err
                     })
             }
         };
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index cf6715e2d73..791ebc5d0ea 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -342,7 +342,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             } else if num_supplied_types != num_method_types {
                 span_err!(self.tcx().sess, self.span, E0036,
                     "incorrect number of type parameters given for this method");
-                Vec::from_elem(num_method_types, ty::mk_err())
+                Vec::from_elem(num_method_types, self.tcx().types.err)
             } else {
                 supplied_method_types
             }
@@ -410,7 +410,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         let method_bounds_substs = match pick.kind {
             probe::ObjectPick(..) => {
                 let mut temp_substs = all_substs.clone();
-                temp_substs.types.get_mut_slice(subst::SelfSpace)[0] = ty::mk_err();
+                temp_substs.types.get_mut_slice(subst::SelfSpace)[0] = self.tcx().types.err;
                 temp_substs
             }
             _ => {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index bb1b24f4b48..7a6b2d54dc1 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -386,7 +386,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemTypesVisitor<'a, 'tcx> {
     fn visit_ty(&mut self, t: &ast::Ty) {
         match t.node {
             ast::TyFixedLengthVec(_, ref expr) => {
-                check_const_in_type(self.ccx, &**expr, ty::mk_uint());
+                check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.uint);
             }
             _ => {}
         }
@@ -505,7 +505,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> {
         match t.node {
             ast::TyFixedLengthVec(ref ty, ref count_expr) => {
                 self.visit_ty(&**ty);
-                check_expr_with_hint(self.fcx, &**count_expr, ty::mk_uint());
+                check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.uint);
             }
             _ => visit::walk_ty(self, t)
         }
@@ -1766,7 +1766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.write_ty(node_id, ty::mk_nil(self.tcx()));
     }
     pub fn write_error(&self, node_id: ast::NodeId) {
-        self.write_ty(node_id, ty::mk_err());
+        self.write_ty(node_id, self.tcx().types.err);
     }
 
     pub fn require_type_meets(&self,
@@ -2072,7 +2072,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
     span_err!(fcx.tcx().sess, sp, E0055,
         "reached the recursion limit while auto-dereferencing {}",
         base_ty.repr(fcx.tcx()));
-    (ty::mk_err(), 0, None)
+    (fcx.tcx().types.err, 0, None)
 }
 
 /// Attempts to resolve a call expression as an overloaded call.
@@ -2228,6 +2228,57 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
     }
 }
 
+/// Autoderefs `base_expr`, looking for a `Slice` impl. If it finds one, installs the relevant
+/// method info and returns the result type (else None).
+fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                  method_call: MethodCall,
+                                  expr: &ast::Expr,
+                                  base_expr: &ast::Expr,
+                                  base_ty: Ty<'tcx>,
+                                  start_expr: &Option<P<ast::Expr>>,
+                                  end_expr: &Option<P<ast::Expr>>,
+                                  mutbl: ast::Mutability)
+                                  -> Option<Ty<'tcx>> // return type is result of slice
+{
+    let lvalue_pref = match mutbl {
+        ast::MutMutable => PreferMutLvalue,
+        ast::MutImmutable => NoPreference
+    };
+
+    let opt_method_ty =
+        autoderef_for_index(fcx, base_expr, base_ty, lvalue_pref, |adjusted_ty, autoderefref| {
+            try_overloaded_slice_step(fcx, method_call, expr, base_expr,
+                                      adjusted_ty, autoderefref, mutbl,
+                                      start_expr, end_expr)
+        });
+
+    // Regardless of whether the lookup succeeds, check the method arguments
+    // so that we have *some* type for each argument.
+    let method_ty_or_err = opt_method_ty.unwrap_or(fcx.tcx().types.err);
+
+    let mut args = vec![];
+    start_expr.as_ref().map(|x| args.push(x));
+    end_expr.as_ref().map(|x| args.push(x));
+
+    check_method_argument_types(fcx,
+                                expr.span,
+                                method_ty_or_err,
+                                expr,
+                                args.as_slice(),
+                                AutorefArgs::Yes,
+                                DontTupleArguments);
+
+    opt_method_ty.map(|method_ty| {
+        let result_ty = ty::ty_fn_ret(method_ty);
+        match result_ty {
+            ty::FnConverging(result_ty) => result_ty,
+            ty::FnDiverging => {
+                fcx.tcx().sess.span_bug(expr.span,
+                                        "slice trait does not define a `!` return")
+            }
+        }
+    })
+}
 
 /// Checks for a `Slice` (or `SliceMut`) impl at the relevant level of autoderef. If it finds one,
 /// installs method info and returns type of method (else None).
@@ -2336,7 +2387,7 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     match ty::index(adjusted_ty) {
         Some(ty) => {
             fcx.write_adjustment(base_expr.id, base_expr.span, ty::AdjustDerefRef(adjustment));
-            return Some((ty::mk_uint(), ty));
+            return Some((fcx.tcx().types.uint, ty));
         }
 
         None => { }
@@ -2398,7 +2449,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         Err(ref err_string) => {
             fcx.tcx().sess.span_err(iterator_expr.span,
                                     err_string[]);
-            return ty::mk_err()
+            return fcx.tcx().types.err
         }
     };
 
@@ -2426,7 +2477,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                 maybe try .iter()",
                                                 ty_string)[]);
             }
-            ty::mk_err()
+            fcx.tcx().types.err
         }
     };
     let return_type = check_method_argument_types(fcx,
@@ -2447,7 +2498,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             let return_type = match return_type {
                 ty::FnConverging(return_type) =>
                     structurally_resolved_type(fcx, iterator_expr.span, return_type),
-                ty::FnDiverging => ty::mk_err()
+                ty::FnDiverging => fcx.tcx().types.err
             };
             match return_type.sty {
                 ty::ty_enum(_, ref substs)
@@ -2455,7 +2506,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     *substs.types.get(subst::TypeSpace, 0)
                 }
                 ty::ty_err => {
-                    ty::mk_err()
+                    fcx.tcx().types.err
                 }
                 _ => {
                     fcx.tcx().sess.span_err(iterator_expr.span,
@@ -2463,11 +2514,11 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                     trait has an unexpected type `{}`",
                                                     fcx.infcx().ty_to_string(return_type))
                                             []);
-                    ty::mk_err()
+                    fcx.tcx().types.err
                 }
             }
         }
-        None => ty::mk_err()
+        None => fcx.tcx().types.err
     }
 }
 
@@ -2480,7 +2531,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          tuple_arguments: TupleArgumentsFlag)
                                          -> ty::FnOutput<'tcx> {
     if ty::type_is_error(method_fn_ty) {
-        let err_inputs = err_args(args_no_rcvr.len());
+        let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
 
         let err_inputs = match tuple_arguments {
             DontTupleArguments => err_inputs,
@@ -2495,7 +2546,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                              autoref_args,
                              false,
                              tuple_arguments);
-        ty::FnConverging(ty::mk_err())
+        ty::FnConverging(fcx.tcx().types.err)
     } else {
         match method_fn_ty.sty {
             ty::ty_bare_fn(_, ref fty) => {
@@ -2550,7 +2601,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         if arg_types.len() == 1 {""} else {"s"},
                         args.len(),
                         if args.len() == 1 {" was"} else {"s were"});
-                    err_args(args.len())
+                    err_args(fcx.tcx(), args.len())
                 } else {
                     (*arg_types).clone()
                 }
@@ -2559,7 +2610,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 span_err!(tcx.sess, sp, E0059,
                     "cannot use call notation; the first type parameter \
                      for the function trait is neither a tuple nor unit");
-                err_args(args.len())
+                err_args(fcx.tcx(), args.len())
             }
         }
     } else if expected_arg_count == supplied_arg_count {
@@ -2575,7 +2626,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 if expected_arg_count == 1 {""} else {"s"},
                 supplied_arg_count,
                 if supplied_arg_count == 1 {" was"} else {"s were"});
-            err_args(supplied_arg_count)
+            err_args(fcx.tcx(), supplied_arg_count)
         }
     } else {
         span_err!(tcx.sess, sp, E0061,
@@ -2584,7 +2635,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             if expected_arg_count == 1 {""} else {"s"},
             supplied_arg_count,
             if supplied_arg_count == 1 {" was"} else {"s were"});
-        err_args(supplied_arg_count)
+        err_args(fcx.tcx(), supplied_arg_count)
     };
 
     debug!("check_argument_types: formal_tys={}",
@@ -2640,7 +2691,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                 // mismatch impl/trait method phase no need to
                                 // ICE here.
                                 // See: #11450
-                                formal_ty = ty::mk_err();
+                                formal_ty = tcx.types.err;
                             }
                         }
                     }
@@ -2691,8 +2742,8 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
-fn err_args<'tcx>(len: uint) -> Vec<Ty<'tcx>> {
-    Vec::from_fn(len, |_| ty::mk_err())
+fn err_args<'tcx>(tcx: &ty::ctxt<'tcx>, len: uint) -> Vec<Ty<'tcx>> {
+    Vec::from_fn(len, |_| tcx.types.err)
 }
 
 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
@@ -2715,27 +2766,28 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     match lit.node {
         ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
         ast::LitBinary(..) => {
-            ty::mk_slice(tcx, tcx.mk_region(ty::ReStatic),
-                         ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
-        }
-        ast::LitByte(_) => ty::mk_u8(),
-        ast::LitChar(_) => ty::mk_char(),
-        ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(t),
-        ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(t),
+            ty::mk_slice(tcx,
+                         tcx.mk_region(ty::ReStatic),
+                         ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
+        }
+        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::UnsuffixedIntLit(_)) => {
             let opt_ty = expected.map_to_option(fcx, |ty| {
                 match ty.sty {
                     ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
-                    ty::ty_char => Some(ty::mk_mach_uint(ast::TyU8)),
-                    ty::ty_ptr(..) => Some(ty::mk_mach_uint(ast::TyU)),
-                    ty::ty_bare_fn(..) => Some(ty::mk_mach_uint(ast::TyU)),
+                    ty::ty_char => Some(tcx.types.u8),
+                    ty::ty_ptr(..) => Some(tcx.types.uint),
+                    ty::ty_bare_fn(..) => Some(tcx.types.uint),
                     _ => None
                 }
             });
             opt_ty.unwrap_or_else(
                 || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
         }
-        ast::LitFloat(_, t) => ty::mk_mach_float(t),
+        ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
         ast::LitFloatUnsuffixed(_) => {
             let opt_ty = expected.map_to_option(fcx, |ty| {
                 match ty.sty {
@@ -2746,7 +2798,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()))
         }
-        ast::LitBool(_) => ty::mk_bool()
+        ast::LitBool(_) => tcx.types.bool
     }
 }
 
@@ -2921,8 +2973,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         // In that case, we check each argument against "error" in order to
         // set up all the node type bindings.
         let error_fn_sig = ty::Binder(FnSig {
-            inputs: err_args(args.len()),
-            output: ty::FnConverging(ty::mk_err()),
+            inputs: err_args(fcx.tcx(), args.len()),
+            output: ty::FnConverging(fcx.tcx().types.err),
             variadic: false
         });
 
@@ -2989,7 +3041,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             Err(error) => {
                 method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
                 fcx.write_error(expr.id);
-                ty::mk_err()
+                fcx.tcx().types.err
             }
         };
 
@@ -3015,7 +3067,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                  id: ast::NodeId,
                                  sp: Span,
                                  expected: Expectation<'tcx>) {
-        check_expr_has_type(fcx, cond_expr, ty::mk_bool());
+        check_expr_has_type(fcx, cond_expr, fcx.tcx().types.bool);
 
         let expected = expected.adjust_for_branches(fcx);
         check_block_with_expected(fcx, then_blk, expected);
@@ -3042,7 +3094,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         let cond_ty = fcx.expr_ty(cond_expr);
         let if_ty = if ty::type_is_error(cond_ty) {
-            ty::mk_err()
+            fcx.tcx().types.err
         } else {
             branches_ty
         };
@@ -3114,14 +3166,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                             autoref_args,
                                             DontTupleArguments) {
                     ty::FnConverging(result_type) => result_type,
-                    ty::FnDiverging => ty::mk_err()
+                    ty::FnDiverging => fcx.tcx().types.err
                 }
             }
             None => {
                 unbound_method();
                 // Check the args anyway
                 // so we get all the error messages
-                let expected_ty = ty::mk_err();
+                let expected_ty = fcx.tcx().types.err;
                 check_method_argument_types(fcx,
                                             op_ex.span,
                                             expected_ty,
@@ -3129,7 +3181,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                             args.as_slice(),
                                             autoref_args,
                                             DontTupleArguments);
-                ty::mk_err()
+                fcx.tcx().types.err
             }
         }
     }
@@ -3155,7 +3207,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
             // Shift is a special case: rhs must be uint, no matter what lhs is
-            check_expr_has_type(fcx, &**rhs, ty::mk_uint());
+            check_expr_has_type(fcx, &**rhs, fcx.tcx().types.uint);
             fcx.write_ty(expr.id, lhs_t);
             return;
         }
@@ -3182,12 +3234,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                 lhs_t,
                                 None
                             );
-                            ty::mk_err()
+                            fcx.tcx().types.err
                         } else {
                             lhs_t
                         }
                     } else {
-                        ty::mk_bool()
+                        fcx.tcx().types.bool
                     }
                 },
                 _ => lhs_t,
@@ -3229,7 +3281,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                    lhs_t,
                                    None);
             check_expr(fcx, &**rhs);
-            ty::mk_err()
+            fcx.tcx().types.err
         };
 
         fcx.write_ty(expr.id, result_t);
@@ -3265,7 +3317,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             ast::BiNe => ("ne", lang.eq_trait()),
             ast::BiAnd | ast::BiOr => {
                 check_expr(fcx, &**rhs);
-                return ty::mk_err();
+                return tcx.types.err;
             }
         };
         lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
@@ -3438,7 +3490,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         // Typecheck each field.
         for field in ast_fields.iter() {
-            let mut expected_field_type = ty::mk_err();
+            let mut expected_field_type = tcx.types.err;
 
             let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
             match pair {
@@ -3545,7 +3597,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                        base_expr.is_none(),
                                        None);
         if ty::type_is_error(fcx.node_ty(id)) {
-            struct_type = ty::mk_err();
+            struct_type = tcx.types.err;
         }
 
         // Check the base expression if necessary.
@@ -3634,7 +3686,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
           if !checked {
               span_err!(tcx.sess, expr.span, E0066,
                   "only the managed heap and exchange heap are currently supported");
-              fcx.write_ty(id, ty::mk_err());
+              fcx.write_ty(id, tcx.types.err);
           }
       }
 
@@ -3734,7 +3786,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                 dereferenced", actual)
                                     }, oprnd_t, None);
                                 }
-                                ty::mk_err()
+                                tcx.types.err
                             }
                         }
                     };
@@ -3791,7 +3843,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
         let oprnd_t = if ty::type_is_error(tm.ty) {
-            ty::mk_err()
+            tcx.types.err
         } else {
             // Note: at this point, we cannot say what the best lifetime
             // is to use for resulting pointer.  We want to use the
@@ -3909,7 +3961,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
       }
       ast::ExprWhile(ref cond, ref body, _) => {
-        check_expr_has_type(fcx, &**cond, ty::mk_bool());
+        check_expr_has_type(fcx, &**cond, tcx.types.bool);
         check_block_no_value(fcx, &**body);
         let cond_ty = fcx.expr_ty(&**cond);
         let body_ty = fcx.node_ty(body.id);
@@ -3989,7 +4041,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
       }
       ast::ExprCast(ref e, ref t) => {
         if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
-            check_expr_with_hint(fcx, &**count_expr, ty::mk_uint());
+            check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
         }
         check_cast(fcx, expr, &**e, &**t);
       }
@@ -4020,7 +4072,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         fcx.write_ty(id, typ);
       }
       ast::ExprRepeat(ref element, ref count_expr) => {
-        check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
+        check_expr_has_type(fcx, &**count_expr, tcx.types.uint);
         let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
 
         let uty = match expected {
@@ -4824,12 +4876,12 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
                     let inh = static_inherited_fields(ccx);
                     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
                     let declty = match hint {
-                        attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(),
+                        attr::ReprAny | attr::ReprPacked | attr::ReprExtern => fcx.tcx().types.int,
                         attr::ReprInt(_, attr::SignedInt(ity)) => {
-                            ty::mk_mach_int(ity)
+                            ty::mk_mach_int(fcx.tcx(), ity)
                         }
                         attr::ReprInt(_, attr::UnsignedInt(ity)) => {
-                            ty::mk_mach_uint(ity)
+                            ty::mk_mach_uint(fcx.tcx(), ity)
                         },
                     };
                     check_const_with_ty(&fcx, e.span, &**e, declty);
@@ -5366,7 +5418,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 , found {} parameter(s)",
                 qualifier, required_len, provided_len);
             substs.types.replace(space,
-                                 Vec::from_elem(desired.len(), ty::mk_err()));
+                                 Vec::from_elem(desired.len(), fcx.tcx().types.err));
             return;
         }
 
@@ -5450,8 +5502,8 @@ pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
             "the type of this value must be known in this \
              context".to_string()
         }, ty, None);
-        demand::suptype(fcx, sp, ty::mk_err(), ty);
-        ty = ty::mk_err();
+        demand::suptype(fcx, sp, fcx.tcx().types.err, ty);
+        ty = fcx.tcx().types.err;
     }
 
     ty
@@ -5554,7 +5606,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
         let (n_tps, inputs, output) = match name.get() {
             "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
             "size_of" |
-            "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
+            "pref_align_of" | "min_align_of" => (1u, Vec::new(), ccx.tcx.types.uint),
             "init" => (1u, Vec::new(), param(ccx, 0)),
             "uninit" => (1u, Vec::new(), param(ccx, 0)),
             "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
@@ -5570,8 +5622,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                   ),
                ty::mk_nil(tcx))
             }
-            "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
-            "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
+            "needs_drop" => (1u, Vec::new(), ccx.tcx.types.bool),
+            "owns_managed" => (1u, Vec::new(), ccx.tcx.types.bool),
 
             "get_tydesc" => {
               let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
@@ -5603,7 +5655,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                       ty: param(ccx, 0),
                       mutbl: ast::MutImmutable
                   }),
-                  ty::mk_int()
+                  ccx.tcx.types.int
                ),
                ty::mk_ptr(tcx, ty::mt {
                    ty: param(ccx, 0),
@@ -5622,7 +5674,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                       ty: param(ccx, 0),
                       mutbl: ast::MutImmutable
                   }),
-                  ty::mk_uint()
+                  tcx.types.uint,
                ),
                ty::mk_nil(tcx))
             }
@@ -5633,88 +5685,88 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                       ty: param(ccx, 0),
                       mutbl: ast::MutMutable
                   }),
-                  ty::mk_u8(),
-                  ty::mk_uint()
+                  tcx.types.u8,
+                  tcx.types.uint,
                ),
                ty::mk_nil(tcx))
             }
-            "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
+            "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
             "powif32" => {
                (0,
-                vec!( ty::mk_f32(), ty::mk_i32() ),
-                ty::mk_f32())
+                vec!( tcx.types.f32, tcx.types.i32 ),
+                tcx.types.f32)
             }
             "powif64" => {
                (0,
-                vec!( ty::mk_f64(), ty::mk_i32() ),
-                ty::mk_f64())
+                vec!( tcx.types.f64, tcx.types.i32 ),
+                tcx.types.f64)
             }
-            "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
+            "sinf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "sinf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "cosf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "cosf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
             "powf32" => {
                (0,
-                vec!( ty::mk_f32(), ty::mk_f32() ),
-                ty::mk_f32())
+                vec!( tcx.types.f32, tcx.types.f32 ),
+                tcx.types.f32)
             }
             "powf64" => {
                (0,
-                vec!( ty::mk_f64(), ty::mk_f64() ),
-                ty::mk_f64())
-            }
-            "expf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "expf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "exp2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "exp2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "logf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "logf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "log2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "log2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
+                vec!( tcx.types.f64, tcx.types.f64 ),
+                tcx.types.f64)
+            }
+            "expf32"   => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "expf64"   => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "exp2f32"  => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "exp2f64"  => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "logf32"   => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "logf64"   => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "log10f32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "log10f64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "log2f32"  => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "log2f64"  => (0, vec!( tcx.types.f64 ), tcx.types.f64),
             "fmaf32" => {
                 (0,
-                 vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
-                 ty::mk_f32())
+                 vec!( tcx.types.f32, tcx.types.f32, tcx.types.f32 ),
+                 tcx.types.f32)
             }
             "fmaf64" => {
                 (0,
-                 vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
-                 ty::mk_f64())
-            }
-            "fabsf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "fabsf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "copysignf32"  => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
-            "copysignf64"  => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
-            "floorf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "floorf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "ceilf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "ceilf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "truncf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "truncf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "rintf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "rintf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "roundf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
-            "roundf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
-            "ctpop8"       => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
-            "ctpop16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
-            "ctpop32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
-            "ctpop64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
-            "ctlz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
-            "ctlz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
-            "ctlz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
-            "ctlz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
-            "cttz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
-            "cttz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
-            "cttz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
-            "cttz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
-            "bswap16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
-            "bswap32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
-            "bswap64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
+                 vec!( tcx.types.f64, tcx.types.f64, tcx.types.f64 ),
+                 tcx.types.f64)
+            }
+            "fabsf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "fabsf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "copysignf32"  => (0, vec!( tcx.types.f32, tcx.types.f32 ), tcx.types.f32),
+            "copysignf64"  => (0, vec!( tcx.types.f64, tcx.types.f64 ), tcx.types.f64),
+            "floorf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "floorf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "ceilf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "ceilf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "truncf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "truncf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "rintf32"      => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "rintf64"      => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "nearbyintf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "nearbyintf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "roundf32"     => (0, vec!( tcx.types.f32 ), tcx.types.f32),
+            "roundf64"     => (0, vec!( tcx.types.f64 ), tcx.types.f64),
+            "ctpop8"       => (0, vec!( tcx.types.u8  ), tcx.types.u8),
+            "ctpop16"      => (0, vec!( tcx.types.u16 ), tcx.types.u16),
+            "ctpop32"      => (0, vec!( tcx.types.u32 ), tcx.types.u32),
+            "ctpop64"      => (0, vec!( tcx.types.u64 ), tcx.types.u64),
+            "ctlz8"        => (0, vec!( tcx.types.u8  ), tcx.types.u8),
+            "ctlz16"       => (0, vec!( tcx.types.u16 ), tcx.types.u16),
+            "ctlz32"       => (0, vec!( tcx.types.u32 ), tcx.types.u32),
+            "ctlz64"       => (0, vec!( tcx.types.u64 ), tcx.types.u64),
+            "cttz8"        => (0, vec!( tcx.types.u8  ), tcx.types.u8),
+            "cttz16"       => (0, vec!( tcx.types.u16 ), tcx.types.u16),
+            "cttz32"       => (0, vec!( tcx.types.u32 ), tcx.types.u32),
+            "cttz64"       => (0, vec!( tcx.types.u64 ), tcx.types.u64),
+            "bswap16"      => (0, vec!( tcx.types.u16 ), tcx.types.u16),
+            "bswap32"      => (0, vec!( tcx.types.u32 ), tcx.types.u32),
+            "bswap64"      => (0, vec!( tcx.types.u64 ), tcx.types.u64),
 
             "volatile_load" =>
                 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
@@ -5722,40 +5774,40 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
                 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
 
             "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
-                (0, vec!(ty::mk_i8(), ty::mk_i8()),
-                ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
+                (0, vec!(tcx.types.i8, tcx.types.i8),
+                ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
 
             "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
-                (0, vec!(ty::mk_i16(), ty::mk_i16()),
-                ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
+                (0, vec!(tcx.types.i16, tcx.types.i16),
+                ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
 
             "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
-                (0, vec!(ty::mk_i32(), ty::mk_i32()),
-                ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
+                (0, vec!(tcx.types.i32, tcx.types.i32),
+                ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
 
             "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
-                (0, vec!(ty::mk_i64(), ty::mk_i64()),
-                ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
+                (0, vec!(tcx.types.i64, tcx.types.i64),
+                ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
 
             "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
-                (0, vec!(ty::mk_u8(), ty::mk_u8()),
-                ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
+                (0, vec!(tcx.types.u8, tcx.types.u8),
+                ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
 
             "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
-                (0, vec!(ty::mk_u16(), ty::mk_u16()),
-                ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
+                (0, vec!(tcx.types.u16, tcx.types.u16),
+                ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
 
             "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
-                (0, vec!(ty::mk_u32(), ty::mk_u32()),
-                ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
+                (0, vec!(tcx.types.u32, tcx.types.u32),
+                ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
 
             "u64_add_with_overflow" | "u64_sub_with_overflow"  | "u64_mul_with_overflow" =>
-                (0, vec!(ty::mk_u64(), ty::mk_u64()),
-                ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
+                (0, vec!(tcx.types.u64, tcx.types.u64),
+                ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
 
-            "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
+            "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
 
-            "assume" => (0, vec![ty::mk_bool()], ty::mk_nil(tcx)),
+            "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
 
             ref other => {
                 span_err!(tcx.sess, it.span, E0093,
diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs
index ff16568aa63..626845613b4 100644
--- a/src/librustc_typeck/check/vtable.rs
+++ b/src/librustc_typeck/check/vtable.rs
@@ -133,7 +133,8 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
                                  object_trait: &ty::TyTrait<'tcx>,
                                  span: Span)
 {
-    let object_trait_ref = object_trait.principal_trait_ref_with_self_ty(tcx, ty::mk_err());
+    let object_trait_ref =
+        object_trait.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
     for tr in traits::supertraits(tcx, object_trait_ref) {
         check_object_safety_inner(tcx, &*tr, span);
     }
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index b123d97d897..5ef9757b91a 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -169,7 +169,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
         match t.node {
             ast::TyFixedLengthVec(ref ty, ref count_expr) => {
                 self.visit_ty(&**ty);
-                write_ty_to_tcx(self.tcx(), count_expr.id, ty::mk_uint());
+                write_ty_to_tcx(self.tcx(), count_expr.id, self.tcx().types.uint);
             }
             _ => visit::walk_ty(self, t)
         }
@@ -441,7 +441,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
                 debug!("Resolver::fold_ty: input type `{}` not fully resolvable",
                        t.repr(self.tcx));
                 self.report_error(e);
-                ty::mk_err()
+                self.tcx().types.err
             }
         }
     }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 74cfbb117e9..6bbf4644414 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -183,7 +183,7 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
     fn ty_infer(&self, span: Span) -> Ty<'tcx> {
         span_err!(self.tcx.sess, span, E0121,
                   "the type placeholder `_` is not allowed within types on item signatures");
-        ty::mk_err()
+        self.tcx().types.err
     }
 
     fn associated_types_of_trait_are_valid(&self, _: Ty<'tcx>, _: ast::DefId)
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index a903c8b0d55..353db82eb02 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -278,11 +278,11 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
                     inputs: vec!(
-                        ty::mk_int(),
-                        ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8()))
+                        tcx.types.int,
+                        ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, tcx.types.u8))
                     ),
-                    output: ty::FnConverging(ty::mk_int()),
-                    variadic: false
+                    output: ty::FnConverging(tcx.types.int),
+                    variadic: false,
                 }),
             }));