about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2015-06-13 13:15:03 -0700
committerEduard Burtescu <edy.burt@gmail.com>2016-03-09 16:45:28 +0200
commitb423a0f9ef488ca4cd9ff620a44566bb441eb21f (patch)
treeae43c17551512f743c1de53035a7f523b32aa6fa /src
parent4b868411afee1208cfb18f7440df991b9f94265f (diff)
downloadrust-b423a0f9ef488ca4cd9ff620a44566bb441eb21f.tar.gz
rust-b423a0f9ef488ca4cd9ff620a44566bb441eb21f.zip
Split TyBareFn into TyFnDef and TyFnPtr.
There's a lot of stuff wrong with the representation of these types:
TyFnDef doesn't actually uniquely identify a function, TyFnPtr is used to
represent method calls, TyFnDef in the sub-expression of a cast isn't
correctly reified, and probably some other stuff I haven't discovered yet.
Splitting them seems like the right first step, though.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/effect.rs3
-rw-r--r--src/librustc/middle/expr_use_visitor.rs2
-rw-r--r--src/librustc/middle/infer/freshen.rs3
-rw-r--r--src/librustc/middle/intrinsicck.rs6
-rw-r--r--src/librustc/middle/traits/coherence.rs3
-rw-r--r--src/librustc/middle/traits/select.rs17
-rw-r--r--src/librustc/middle/ty/adjustment.rs6
-rw-r--r--src/librustc/middle/ty/cast.rs4
-rw-r--r--src/librustc/middle/ty/contents.rs2
-rw-r--r--src/librustc/middle/ty/context.rs24
-rw-r--r--src/librustc/middle/ty/error.rs4
-rw-r--r--src/librustc/middle/ty/fast_reject.rs2
-rw-r--r--src/librustc/middle/ty/flags.rs2
-rw-r--r--src/librustc/middle/ty/outlives.rs3
-rw-r--r--src/librustc/middle/ty/relate.rs12
-rw-r--r--src/librustc/middle/ty/structural_impls.rs10
-rw-r--r--src/librustc/middle/ty/sty.rs43
-rw-r--r--src/librustc/middle/ty/util.rs15
-rw-r--r--src/librustc/middle/ty/walk.rs2
-rw-r--r--src/librustc/middle/ty/wf.rs4
-rw-r--r--src/librustc/util/ppaux.rs22
-rw-r--r--src/librustc_driver/test.rs19
-rw-r--r--src/librustc_lint/builtin.rs4
-rw-r--r--src/librustc_lint/types.rs6
-rw-r--r--src/librustc_metadata/decoder.rs7
-rw-r--r--src/librustc_metadata/tydecode.rs4
-rw-r--r--src/librustc_metadata/tyencode.rs4
-rw-r--r--src/librustc_mir/build/expr/into.rs4
-rw-r--r--src/librustc_mir/hair/cx/expr.rs6
-rw-r--r--src/librustc_mir/transform/type_check.rs2
-rw-r--r--src/librustc_passes/consts.rs2
-rw-r--r--src/librustc_privacy/lib.rs2
-rw-r--r--src/librustc_trans/trans/adt.rs4
-rw-r--r--src/librustc_trans/trans/attributes.rs4
-rw-r--r--src/librustc_trans/trans/base.rs8
-rw-r--r--src/librustc_trans/trans/callee.rs47
-rw-r--r--src/librustc_trans/trans/closure.rs31
-rw-r--r--src/librustc_trans/trans/collector.rs35
-rw-r--r--src/librustc_trans/trans/common.rs2
-rw-r--r--src/librustc_trans/trans/consts.rs2
-rw-r--r--src/librustc_trans/trans/debuginfo/metadata.rs5
-rw-r--r--src/librustc_trans/trans/debuginfo/mod.rs2
-rw-r--r--src/librustc_trans/trans/debuginfo/type_names.rs3
-rw-r--r--src/librustc_trans/trans/declare.rs3
-rw-r--r--src/librustc_trans/trans/expr.rs2
-rw-r--r--src/librustc_trans/trans/foreign.rs14
-rw-r--r--src/librustc_trans/trans/intrinsic.rs15
-rw-r--r--src/librustc_trans/trans/meth.rs34
-rw-r--r--src/librustc_trans/trans/mir/block.rs19
-rw-r--r--src/librustc_trans/trans/type_of.rs6
-rw-r--r--src/librustc_typeck/astconv.rs3
-rw-r--r--src/librustc_typeck/check/callee.rs5
-rw-r--r--src/librustc_typeck/check/coercion.rs10
-rw-r--r--src/librustc_typeck/check/compare_method.rs12
-rw-r--r--src/librustc_typeck/check/dropck.rs2
-rw-r--r--src/librustc_typeck/check/intrinsic.rs10
-rw-r--r--src/librustc_typeck/check/method/confirm.rs6
-rw-r--r--src/librustc_typeck/check/method/mod.rs4
-rw-r--r--src/librustc_typeck/check/method/suggest.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs6
-rw-r--r--src/librustc_typeck/check/regionck.rs2
-rw-r--r--src/librustc_typeck/check/wfcheck.rs4
-rw-r--r--src/librustc_typeck/coherence/mod.rs6
-rw-r--r--src/librustc_typeck/collect.rs25
-rw-r--r--src/librustc_typeck/constrained_type_params.rs3
-rw-r--r--src/librustc_typeck/lib.rs13
-rw-r--r--src/librustc_typeck/variance/constraints.rs3
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/mod.rs3
-rw-r--r--src/test/auxiliary/issue13507.rs72
-rw-r--r--src/test/compile-fail/invalid-intrinsic.rs16
-rw-r--r--src/test/compile-fail/variadic-ffi-3.rs2
-rw-r--r--src/test/run-pass/issue-13507-2.rs34
73 files changed, 406 insertions, 324 deletions
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index e3d05388f52..5f9fb791598 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -44,7 +44,8 @@ enum RootUnsafeContext {
 
 fn type_is_unsafe_function(ty: Ty) -> bool {
     match ty.sty {
-        ty::TyBareFn(_, ref f) => f.unsafety == hir::Unsafety::Unsafe,
+        ty::TyFnDef(_, ref f) |
+        ty::TyFnPtr(ref f) => f.unsafety == hir::Unsafety::Unsafe,
         _ => false,
     }
 }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 5ddea691743..a87ce1206b4 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -556,7 +556,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                callee, callee_ty);
         let call_scope = self.tcx().region_maps.node_extent(call.id);
         match callee_ty.sty {
-            ty::TyBareFn(..) => {
+            ty::TyFnDef(..) | ty::TyFnPtr(_) => {
                 self.consume_expr(callee);
             }
             ty::TyError => { }
diff --git a/src/librustc/middle/infer/freshen.rs b/src/librustc/middle/infer/freshen.rs
index b64fa688d51..6c0dd9b608d 100644
--- a/src/librustc/middle/infer/freshen.rs
+++ b/src/librustc/middle/infer/freshen.rs
@@ -161,7 +161,8 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
             ty::TySlice(..) |
             ty::TyRawPtr(..) |
             ty::TyRef(..) |
-            ty::TyBareFn(..) |
+            ty::TyFnDef(..) |
+            ty::TyFnPtr(_) |
             ty::TyTrait(..) |
             ty::TyStruct(..) |
             ty::TyClosure(..) |
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 7de8904e3f2..1293d8e833f 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -12,7 +12,7 @@ use dep_graph::DepNode;
 use middle::def::Def;
 use middle::def_id::DefId;
 use middle::subst::{Subst, Substs, EnumeratedItems};
-use middle::ty::{TransmuteRestriction, TyCtxt, TyBareFn};
+use middle::ty::{TransmuteRestriction, TyCtxt};
 use middle::ty::{self, Ty, TypeFoldable};
 
 use std::fmt;
@@ -53,7 +53,7 @@ struct IntrinsicCheckingVisitor<'a, 'tcx: 'a> {
 impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
     fn def_id_is_transmute(&self, def_id: DefId) -> bool {
         let intrinsic = match self.tcx.lookup_item_type(def_id).ty.sty {
-            ty::TyBareFn(_, ref bfty) => bfty.abi == RustIntrinsic,
+            ty::TyFnDef(_, ref bfty) => bfty.abi == RustIntrinsic,
             _ => return false
         };
         intrinsic && self.tcx.item_name(def_id).as_str() == "transmute"
@@ -238,7 +238,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
                 Def::Fn(did) if self.def_id_is_transmute(did) => {
                     let typ = self.tcx.node_id_to_type(expr.id);
                     match typ.sty {
-                        TyBareFn(_, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
+                        ty::TyFnDef(_, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
                             if let ty::FnConverging(to) = bare_fn_ty.sig.0.output {
                                 let from = bare_fn_ty.sig.0.inputs[0];
                                 self.check_transmute(expr.span, from, to, expr.id);
diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs
index b0970457892..b79849e87ff 100644
--- a/src/librustc/middle/traits/coherence.rs
+++ b/src/librustc/middle/traits/coherence.rs
@@ -301,7 +301,8 @@ fn ty_is_local_constructor<'tcx>(tcx: &TyCtxt<'tcx>,
         ty::TyUint(..) |
         ty::TyFloat(..) |
         ty::TyStr |
-        ty::TyBareFn(..) |
+        ty::TyFnDef(..) |
+        ty::TyFnPtr(_) |
         ty::TyArray(..) |
         ty::TySlice(..) |
         ty::TyRawPtr(..) |
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 373ec37663f..6cd85a522b5 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -1286,7 +1286,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // provide an impl, but only for suitable `fn` pointers
-            ty::TyBareFn(_, &ty::BareFnTy {
+            ty::TyFnDef(_, &ty::BareFnTy {
+                unsafety: hir::Unsafety::Normal,
+                abi: Abi::Rust,
+                sig: ty::Binder(ty::FnSig {
+                    inputs: _,
+                    output: ty::FnConverging(_),
+                    variadic: false
+                })
+            }) |
+            ty::TyFnPtr(&ty::BareFnTy {
                 unsafety: hir::Unsafety::Normal,
                 abi: Abi::Rust,
                 sig: ty::Binder(ty::FnSig {
@@ -1646,7 +1655,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::TyInt(_) |
             ty::TyBool |
             ty::TyFloat(_) |
-            ty::TyBareFn(..) |
+            ty::TyFnDef(..) |
+            ty::TyFnPtr(_) |
             ty::TyChar => {
                 // safe for everything
                 ok_if(Vec::new())
@@ -1850,7 +1860,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::TyInt(_) |
             ty::TyBool |
             ty::TyFloat(_) |
-            ty::TyBareFn(..) |
+            ty::TyFnDef(..) |
+            ty::TyFnPtr(_) |
             ty::TyStr |
             ty::TyError |
             ty::TyInfer(ty::IntVar(_)) |
diff --git a/src/librustc/middle/ty/adjustment.rs b/src/librustc/middle/ty/adjustment.rs
index 40581cfa1c5..ca614f84c0b 100644
--- a/src/librustc/middle/ty/adjustment.rs
+++ b/src/librustc/middle/ty/adjustment.rs
@@ -155,8 +155,8 @@ impl<'tcx> ty::TyS<'tcx> {
                 match *adjustment {
                     AdjustReifyFnPointer => {
                         match self.sty {
-                            ty::TyBareFn(Some(_), b) => {
-                                cx.mk_fn(None, b)
+                            ty::TyFnDef(_, b) => {
+                                cx.mk_ty(ty::TyFnPtr(b))
                             }
                             _ => {
                                 cx.sess.bug(
@@ -168,7 +168,7 @@ impl<'tcx> ty::TyS<'tcx> {
 
                     AdjustUnsafeFnPointer => {
                         match self.sty {
-                            ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b),
+                            ty::TyFnPtr(b) => cx.safe_to_unsafe_fn_ty(b),
                             ref b => {
                                 cx.sess.bug(
                                     &format!("AdjustUnsafeFnPointer adjustment on non-fn-ptr: \
diff --git a/src/librustc/middle/ty/cast.rs b/src/librustc/middle/ty/cast.rs
index 8233b6b2b2b..ac308f56434 100644
--- a/src/librustc/middle/ty/cast.rs
+++ b/src/librustc/middle/ty/cast.rs
@@ -69,7 +69,9 @@ impl<'tcx> CastTy<'tcx> {
                 Some(CastTy::Int(IntTy::CEnum)),
             ty::TyRawPtr(ref mt) => Some(CastTy::Ptr(mt)),
             ty::TyRef(_, ref mt) => Some(CastTy::RPtr(mt)),
-            ty::TyBareFn(..) => Some(CastTy::FnPtr),
+            // FIXME: Treating TyFnDef as a pointer here is a bit dubious;
+            // we should be coercing the operand to an actual pointer.
+            ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(CastTy::FnPtr),
             _ => None,
         }
     }
diff --git a/src/librustc/middle/ty/contents.rs b/src/librustc/middle/ty/contents.rs
index 8dfa0262f2b..47a15a14b41 100644
--- a/src/librustc/middle/ty/contents.rs
+++ b/src/librustc/middle/ty/contents.rs
@@ -187,7 +187,7 @@ impl<'tcx> ty::TyS<'tcx> {
                 // Scalar and unique types are sendable, and durable
                 ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
                 ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
-                ty::TyBareFn(..) | ty::TyChar => {
+                ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar => {
                     TC::None
                 }
 
diff --git a/src/librustc/middle/ty/context.rs b/src/librustc/middle/ty/context.rs
index ffc52af19bb..8d74c5f3193 100644
--- a/src/librustc/middle/ty/context.rs
+++ b/src/librustc/middle/ty/context.rs
@@ -734,8 +734,8 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn print_debug_stats(&self) {
         sty_debug_print!(
             self,
-            TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyBareFn, TyTrait,
-            TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
+            TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr,
+            TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection);
 
         println!("Substs interner: #{}", self.substs_interner.borrow().len());
         println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
@@ -792,12 +792,11 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Create an unsafe fn ty based on a safe fn ty.
     pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
         assert_eq!(bare_fn.unsafety, hir::Unsafety::Normal);
-        let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy {
+        self.mk_fn_ptr(ty::BareFnTy {
             unsafety: hir::Unsafety::Unsafe,
             abi: bare_fn.abi,
             sig: bare_fn.sig.clone()
-        });
-        self.mk_fn(None, unsafe_fn_ty_a)
+        })
     }
 
     pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> {
@@ -946,10 +945,13 @@ impl<'tcx> TyCtxt<'tcx> {
         self.mk_ty(TyBool)
     }
 
-    pub fn mk_fn(&self,
-                 opt_def_id: Option<DefId>,
-                 fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(TyBareFn(opt_def_id, fty))
+    pub fn mk_fn_def(&self, def_id: DefId,
+                     fty: BareFnTy<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyFnDef(def_id, self.mk_bare_fn(fty)))
+    }
+
+    pub fn mk_fn_ptr(&self, fty: BareFnTy<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyFnPtr(self.mk_bare_fn(fty)))
     }
 
     pub fn mk_ctor_fn(&self,
@@ -957,7 +959,7 @@ impl<'tcx> TyCtxt<'tcx> {
                       input_tys: &[Ty<'tcx>],
                       output: Ty<'tcx>) -> Ty<'tcx> {
         let input_args = input_tys.iter().cloned().collect();
-        self.mk_fn(Some(def_id), self.mk_bare_fn(BareFnTy {
+        self.mk_fn_def(def_id, BareFnTy {
             unsafety: hir::Unsafety::Normal,
             abi: Abi::Rust,
             sig: ty::Binder(ty::FnSig {
@@ -965,7 +967,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 output: ty::FnConverging(output),
                 variadic: false
             })
-        }))
+        })
     }
 
     pub fn mk_trait(&self,
diff --git a/src/librustc/middle/ty/error.rs b/src/librustc/middle/ty/error.rs
index 39a5069e129..1033af5f331 100644
--- a/src/librustc/middle/ty/error.rs
+++ b/src/librustc/middle/ty/error.rs
@@ -223,8 +223,8 @@ impl<'tcx> ty::TyS<'tcx> {
             ty::TySlice(_) => "slice".to_string(),
             ty::TyRawPtr(_) => "*-ptr".to_string(),
             ty::TyRef(_, _) => "&-ptr".to_string(),
-            ty::TyBareFn(Some(_), _) => format!("fn item"),
-            ty::TyBareFn(None, _) => "fn pointer".to_string(),
+            ty::TyFnDef(..) => format!("fn item"),
+            ty::TyFnPtr(_) => "fn pointer".to_string(),
             ty::TyTrait(ref inner) => {
                 format!("trait {}", cx.item_path_str(inner.principal_def_id()))
             }
diff --git a/src/librustc/middle/ty/fast_reject.rs b/src/librustc/middle/ty/fast_reject.rs
index a42e5fc2e85..285fa5d8827 100644
--- a/src/librustc/middle/ty/fast_reject.rs
+++ b/src/librustc/middle/ty/fast_reject.rs
@@ -83,7 +83,7 @@ pub fn simplify_type(tcx: &TyCtxt,
         ty::TyTuple(ref tys) => {
             Some(TupleSimplifiedType(tys.len()))
         }
-        ty::TyBareFn(_, ref f) => {
+        ty::TyFnDef(_, ref f) | ty::TyFnPtr(ref f) => {
             Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
         }
         ty::TyProjection(_) | ty::TyParam(_) => {
diff --git a/src/librustc/middle/ty/flags.rs b/src/librustc/middle/ty/flags.rs
index a0b03fe8126..04afb45bcf1 100644
--- a/src/librustc/middle/ty/flags.rs
+++ b/src/librustc/middle/ty/flags.rs
@@ -134,7 +134,7 @@ impl FlagComputation {
                 self.add_tys(&ts[..]);
             }
 
-            &ty::TyBareFn(_, ref f) => {
+            &ty::TyFnDef(_, ref f) | &ty::TyFnPtr(ref f) => {
                 self.add_fn_sig(&f.sig);
             }
         }
diff --git a/src/librustc/middle/ty/outlives.rs b/src/librustc/middle/ty/outlives.rs
index fc20c1bcb85..9439180a6cd 100644
--- a/src/librustc/middle/ty/outlives.rs
+++ b/src/librustc/middle/ty/outlives.rs
@@ -182,7 +182,8 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
         ty::TyRawPtr(..) |      // ...
         ty::TyRef(..) |         // OutlivesReference
         ty::TyTuple(..) |       // ...
-        ty::TyBareFn(..) |      // OutlivesFunction (*)
+        ty::TyFnDef(..) |       // OutlivesFunction (*)
+        ty::TyFnPtr(_) |        // OutlivesFunction (*)
         ty::TyTrait(..) |       // OutlivesObject, OutlivesFragment (*)
         ty::TyError => {
             // (*) Bare functions and traits are both binders. In the
diff --git a/src/librustc/middle/ty/relate.rs b/src/librustc/middle/ty/relate.rs
index 5d6106a6d77..4c146e93174 100644
--- a/src/librustc/middle/ty/relate.rs
+++ b/src/librustc/middle/ty/relate.rs
@@ -568,11 +568,17 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
             }
         }
 
-        (&ty::TyBareFn(a_opt_def_id, a_fty), &ty::TyBareFn(b_opt_def_id, b_fty))
-            if a_opt_def_id == b_opt_def_id =>
+        (&ty::TyFnDef(a_def_id, a_fty), &ty::TyFnDef(b_def_id, b_fty))
+            if a_def_id == b_def_id =>
         {
             let fty = try!(relation.relate(a_fty, b_fty));
-            Ok(tcx.mk_fn(a_opt_def_id, tcx.mk_bare_fn(fty)))
+            Ok(tcx.mk_fn_def(a_def_id, fty))
+        }
+
+        (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) =>
+        {
+            let fty = try!(relation.relate(a_fty, b_fty));
+            Ok(tcx.mk_fn_ptr(fty))
         }
 
         (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) =>
diff --git a/src/librustc/middle/ty/structural_impls.rs b/src/librustc/middle/ty/structural_impls.rs
index 001ea02a27c..b504bba01b9 100644
--- a/src/librustc/middle/ty/structural_impls.rs
+++ b/src/librustc/middle/ty/structural_impls.rs
@@ -282,9 +282,13 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             }
             ty::TyTrait(ref trait_ty) => ty::TyTrait(trait_ty.fold_with(folder)),
             ty::TyTuple(ref ts) => ty::TyTuple(ts.fold_with(folder)),
-            ty::TyBareFn(opt_def_id, ref f) => {
+            ty::TyFnDef(def_id, ref f) => {
                 let bfn = f.fold_with(folder);
-                ty::TyBareFn(opt_def_id, folder.tcx().mk_bare_fn(bfn))
+                ty::TyFnDef(def_id, folder.tcx().mk_bare_fn(bfn))
+            }
+            ty::TyFnPtr(ref f) => {
+                let bfn = f.fold_with(folder);
+                ty::TyFnPtr(folder.tcx().mk_bare_fn(bfn))
             }
             ty::TyRef(r, ref tm) => {
                 let r = r.fold_with(folder);
@@ -318,7 +322,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::TyEnum(_tid, ref substs) => substs.visit_with(visitor),
             ty::TyTrait(ref trait_ty) => trait_ty.visit_with(visitor),
             ty::TyTuple(ref ts) => ts.visit_with(visitor),
-            ty::TyBareFn(_opt_def_id, ref f) => f.visit_with(visitor),
+            ty::TyFnDef(_, ref f) | ty::TyFnPtr(ref f) => f.visit_with(visitor),
             ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
             ty::TyStruct(_did, ref substs) => substs.visit_with(visitor),
             ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
diff --git a/src/librustc/middle/ty/sty.rs b/src/librustc/middle/ty/sty.rs
index c8f8e073832..217ae8fd494 100644
--- a/src/librustc/middle/ty/sty.rs
+++ b/src/librustc/middle/ty/sty.rs
@@ -127,14 +127,16 @@ pub enum TypeVariants<'tcx> {
     /// `&a mut T` or `&'a T`.
     TyRef(&'tcx Region, TypeAndMut<'tcx>),
 
-    /// If the def-id is Some(_), then this is the type of a specific
-    /// fn item. Otherwise, if None(_), it is a fn pointer type.
-    ///
-    /// FIXME: Conflating function pointers and the type of a
-    /// function is probably a terrible idea; a function pointer is a
-    /// value with a specific type, but a function can be polymorphic
-    /// or dynamically dispatched.
-    TyBareFn(Option<DefId>, &'tcx BareFnTy<'tcx>),
+    /// The anonymous type of a function declaration/definition. Each
+    /// function has a unique type.
+    /// FIXME: Does this need to include substitutions?
+    /// `g::<i32>` and `g::<u32>` should have different types.
+    TyFnDef(DefId, &'tcx BareFnTy<'tcx>),
+
+    /// A pointer to a function.  Written as `fn() -> i32`.
+    /// FIXME: This is currently also used to represent the callee of a method;
+    /// see ty::MethodCallee etc.
+    TyFnPtr(&'tcx BareFnTy<'tcx>),
 
     /// A trait, defined with `trait`.
     TyTrait(Box<TraitTy<'tcx>>),
@@ -1029,7 +1031,7 @@ impl<'tcx> TyS<'tcx> {
         match self.sty {
             TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
             TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) |
-            TyBareFn(..) | TyRawPtr(_) => true,
+            TyFnDef(..) | TyFnPtr(_) | TyRawPtr(_) => true,
             _ => false
         }
     }
@@ -1080,20 +1082,6 @@ impl<'tcx> TyS<'tcx> {
         }
     }
 
-    pub fn is_bare_fn(&self) -> bool {
-        match self.sty {
-            TyBareFn(..) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_bare_fn_item(&self) -> bool {
-        match self.sty {
-            TyBareFn(Some(_), _) => true,
-            _ => false
-        }
-    }
-
     pub fn is_fp(&self) -> bool {
         match self.sty {
             TyInfer(FloatVar(_)) | TyFloat(_) => true,
@@ -1154,7 +1142,7 @@ impl<'tcx> TyS<'tcx> {
 
     pub fn fn_sig(&self) -> &'tcx PolyFnSig<'tcx> {
         match self.sty {
-            TyBareFn(_, ref f) => &f.sig,
+            TyFnDef(_, ref f) | TyFnPtr(ref f) => &f.sig,
             _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self)
         }
     }
@@ -1162,7 +1150,7 @@ impl<'tcx> TyS<'tcx> {
     /// Returns the ABI of the given function.
     pub fn fn_abi(&self) -> abi::Abi {
         match self.sty {
-            TyBareFn(_, ref f) => f.abi,
+            TyFnDef(_, ref f) | TyFnPtr(ref f) => f.abi,
             _ => panic!("Ty::fn_abi() called on non-fn type"),
         }
     }
@@ -1178,7 +1166,7 @@ impl<'tcx> TyS<'tcx> {
 
     pub fn is_fn(&self) -> bool {
         match self.sty {
-            TyBareFn(..) => true,
+            TyFnDef(..) | TyFnPtr(_) => true,
             _ => false
         }
     }
@@ -1224,7 +1212,8 @@ impl<'tcx> TyS<'tcx> {
             TyProjection(ref data) => {
                 data.trait_ref.substs.regions().as_slice().to_vec()
             }
-            TyBareFn(..) |
+            TyFnDef(..) |
+            TyFnPtr(_) |
             TyBool |
             TyChar |
             TyInt(_) |
diff --git a/src/librustc/middle/ty/util.rs b/src/librustc/middle/ty/util.rs
index 7c32d931fff..6947c7dd4dc 100644
--- a/src/librustc/middle/ty/util.rs
+++ b/src/librustc/middle/ty/util.rs
@@ -514,9 +514,16 @@ impl<'tcx> TyCtxt<'tcx> {
                         region(state, *r);
                         mt(state, m);
                     }
-                    TyBareFn(opt_def_id, ref b) => {
+                    TyFnDef(def_id, ref b) => {
                         byte!(14);
-                        hash!(opt_def_id);
+                        hash!(def_id);
+                        hash!(b.unsafety);
+                        hash!(b.abi);
+                        fn_sig(state, &b.sig);
+                        return false;
+                    }
+                    TyFnPtr(ref b) => {
+                        byte!(15);
                         hash!(b.unsafety);
                         hash!(b.abi);
                         fn_sig(state, &b.sig);
@@ -677,7 +684,7 @@ impl<'tcx> ty::TyS<'tcx> {
         // Fast-path for primitive types
         let result = match self.sty {
             TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-            TyRawPtr(..) | TyBareFn(..) | TyRef(_, TypeAndMut {
+            TyRawPtr(..) | TyFnDef(..) | TyFnPtr(_) | TyRef(_, TypeAndMut {
                 mutbl: hir::MutImmutable, ..
             }) => Some(false),
 
@@ -719,7 +726,7 @@ impl<'tcx> ty::TyS<'tcx> {
         // Fast-path for primitive types
         let result = match self.sty {
             TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-            TyBox(..) | TyRawPtr(..) | TyRef(..) | TyBareFn(..) |
+            TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
             TyArray(..) | TyTuple(..) | TyClosure(..) => Some(true),
 
             TyStr | TyTrait(..) | TySlice(_) => Some(false),
diff --git a/src/librustc/middle/ty/walk.rs b/src/librustc/middle/ty/walk.rs
index 81cad448690..0d226e22db9 100644
--- a/src/librustc/middle/ty/walk.rs
+++ b/src/librustc/middle/ty/walk.rs
@@ -98,7 +98,7 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
         ty::TyTuple(ref ts) => {
             push_reversed(stack, ts);
         }
-        ty::TyBareFn(_, ref ft) => {
+        ty::TyFnDef(_, ref ft) | ty::TyFnPtr(ref ft) => {
             push_sig_subtypes(stack, &ft.sig);
         }
     }
diff --git a/src/librustc/middle/ty/wf.rs b/src/librustc/middle/ty/wf.rs
index c6d1bc8d649..5f81d27a1f6 100644
--- a/src/librustc/middle/ty/wf.rs
+++ b/src/librustc/middle/ty/wf.rs
@@ -354,8 +354,8 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
                     // WFedness.)
                 }
 
-                ty::TyBareFn(..) => {
-                    // let the loop iterator into the argument/return
+                ty::TyFnDef(..) | ty::TyFnPtr(_) => {
+                    // let the loop iterate into the argument/return
                     // types appearing in the fn signature
                 }
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 9c92208191e..2bf8879f3a0 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -13,7 +13,7 @@ use middle::def_id::DefId;
 use middle::subst::{self, Subst};
 use middle::ty::{BrAnon, BrEnv, BrFresh, BrNamed};
 use middle::ty::{TyBool, TyChar, TyStruct, TyEnum};
-use middle::ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyBareFn};
+use middle::ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
 use middle::ty::{TyParam, TyRawPtr, TyRef, TyTuple};
 use middle::ty::TyClosure;
 use middle::ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
@@ -812,7 +812,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
                 }
                 write!(f, ")")
             }
-            TyBareFn(opt_def_id, ref bare_fn) => {
+            TyFnDef(def_id, ref bare_fn) => {
                 if bare_fn.unsafety == hir::Unsafety::Unsafe {
                     try!(write!(f, "unsafe "));
                 }
@@ -823,12 +823,20 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
 
                 try!(write!(f, "{}", bare_fn.sig.0));
 
-                if let Some(def_id) = opt_def_id {
-                    try!(write!(f, " {{{}}}", ty::tls::with(|tcx| {
-                        tcx.item_path_str(def_id)
-                    })));
+                write!(f, " {{{}}}", ty::tls::with(|tcx| {
+                    tcx.item_path_str(def_id)
+                }))
+            }
+            TyFnPtr(ref bare_fn) => {
+                if bare_fn.unsafety == hir::Unsafety::Unsafe {
+                    try!(write!(f, "unsafe "));
                 }
-                Ok(())
+
+                if bare_fn.abi != Abi::Rust {
+                    try!(write!(f, "extern {} ", bare_fn.abi));
+                }
+
+                write!(f, "{}", bare_fn.sig.0)
             }
             TyInfer(infer_ty) => write!(f, "{}", infer_ty),
             TyError => write!(f, "[type error]"),
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index abeaffe80ab..ce84147559c 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -261,16 +261,15 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
 
     pub fn t_fn(&self, input_tys: &[Ty<'tcx>], output_ty: Ty<'tcx>) -> Ty<'tcx> {
         let input_args = input_tys.iter().cloned().collect();
-        self.infcx.tcx.mk_fn(None,
-                             self.infcx.tcx.mk_bare_fn(ty::BareFnTy {
-                                 unsafety: hir::Unsafety::Normal,
-                                 abi: Abi::Rust,
-                                 sig: ty::Binder(ty::FnSig {
-                                     inputs: input_args,
-                                     output: ty::FnConverging(output_ty),
-                                     variadic: false,
-                                 }),
-                             }))
+        self.infcx.tcx.mk_fn_ptr(ty::BareFnTy {
+            unsafety: hir::Unsafety::Normal,
+            abi: Abi::Rust,
+            sig: ty::Binder(ty::FnSig {
+                inputs: input_args,
+                output: ty::FnConverging(output_ty),
+                variadic: false,
+            }),
+        })
     }
 
     pub fn t_nil(&self) -> Ty<'tcx> {
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 86ab8d45e4e..05a0eab4150 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1065,7 +1065,7 @@ impl LateLintPass for MutableTransmutes {
                 }
                 let typ = cx.tcx.node_id_to_type(expr.id);
                 match typ.sty {
-                    ty::TyBareFn(_, ref bare_fn) if bare_fn.abi == RustIntrinsic => {
+                    ty::TyFnDef(_, ref bare_fn) if bare_fn.abi == RustIntrinsic => {
                         if let ty::FnConverging(to) = bare_fn.sig.0.output {
                             let from = bare_fn.sig.0.inputs[0];
                             return Some((&from.sty, &to.sty));
@@ -1079,7 +1079,7 @@ impl LateLintPass for MutableTransmutes {
 
         fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool {
             match cx.tcx.lookup_item_type(def_id).ty.sty {
-                ty::TyBareFn(_, ref bfty) if bfty.abi == RustIntrinsic => (),
+                ty::TyFnDef(_, ref bfty) if bfty.abi == RustIntrinsic => (),
                 _ => return false
             }
             cx.tcx.with_path(def_id, |path| match path.last() {
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index c7cb2d15a09..10535549ceb 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -391,7 +391,7 @@ fn is_repr_nullable_ptr<'tcx>(tcx: &TyCtxt<'tcx>,
 
         if def.variants[data_idx].fields.len() == 1 {
             match def.variants[data_idx].fields[0].ty(tcx, substs).sty {
-                ty::TyBareFn(None, _) => { return true; }
+                ty::TyFnPtr(_) => { return true; }
                 ty::TyRef(..) => { return true; }
                 _ => { }
             }
@@ -556,7 +556,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                 self.check_type_for_ffi(cache, ty)
             }
 
-            ty::TyBareFn(None, bare_fn) => {
+            ty::TyFnPtr(bare_fn) => {
                 match bare_fn.abi {
                     Abi::Rust |
                     Abi::RustIntrinsic |
@@ -595,7 +595,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
             ty::TyParam(..) | ty::TyInfer(..) | ty::TyError |
             ty::TyClosure(..) | ty::TyProjection(..) |
-            ty::TyBareFn(Some(_), _) => {
+            ty::TyFnDef(..) => {
                 panic!("Unexpected type in foreign function")
             }
         }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index e286e028f33..3ddfa1d2730 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -472,7 +472,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
                    variant.name,
                    ctor_ty);
             let field_tys = match ctor_ty.sty {
-                ty::TyBareFn(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
+                ty::TyFnDef(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
                     ref inputs, ..
                 }), ..}) => {
                     // tuple-struct constructors don't have escaping regions
@@ -988,7 +988,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
             let predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics);
             let ity = tcx.lookup_item_type(def_id).ty;
             let fty = match ity.sty {
-                ty::TyBareFn(_, fty) => fty.clone(),
+                ty::TyFnDef(_, fty) => fty.clone(),
                 _ => tcx.sess.bug(&format!(
                     "the type {:?} of the method {:?} is not a function?",
                     ity, name))
@@ -1582,7 +1582,8 @@ pub fn is_extern_item(cdata: Cmd, id: DefIndex, tcx: &TyCtxt) -> bool {
             let ty::TypeScheme { generics, ty } = get_type(cdata, id, tcx);
             let no_generics = generics.types.is_empty();
             match ty.sty {
-                ty::TyBareFn(_, fn_ty) if fn_ty.abi != Abi::Rust => return no_generics,
+                ty::TyFnDef(_, fn_ty) | ty::TyFnPtr(fn_ty)
+                    if fn_ty.abi != Abi::Rust => return no_generics,
                 _ => no_generics,
             }
         },
diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs
index bf5a97232fc..b263a0c166f 100644
--- a/src/librustc_metadata/tydecode.rs
+++ b/src/librustc_metadata/tydecode.rs
@@ -380,10 +380,10 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             }
             'F' => {
                 let def_id = self.parse_def();
-                return tcx.mk_fn(Some(def_id), tcx.mk_bare_fn(self.parse_bare_fn_ty()));
+                return tcx.mk_fn_def(def_id, self.parse_bare_fn_ty());
             }
             'G' => {
-                return tcx.mk_fn(None, tcx.mk_bare_fn(self.parse_bare_fn_ty()));
+                return tcx.mk_fn_ptr(self.parse_bare_fn_ty());
             }
             '#' => {
                 // This is a hacky little caching scheme. The idea is that if we encode
diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs
index 7289cd2b5b3..bf180b19b3f 100644
--- a/src/librustc_metadata/tyencode.rs
+++ b/src/librustc_metadata/tyencode.rs
@@ -135,12 +135,12 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
         ty::TyStr => {
             write!(w, "v");
         }
-        ty::TyBareFn(Some(def_id), f) => {
+        ty::TyFnDef(def_id, f) => {
             write!(w, "F");
             write!(w, "{}|", (cx.ds)(def_id));
             enc_bare_fn_ty(w, cx, f);
         }
-        ty::TyBareFn(None, f) => {
+        ty::TyFnPtr(f) => {
             write!(w, "G");
             enc_bare_fn_ty(w, cx, f);
         }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index ca00b99b108..b5584330557 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -239,7 +239,9 @@ impl<'a,'tcx> Builder<'a,'tcx> {
             }
             ExprKind::Call { ty, fun, args } => {
                 let diverges = match ty.sty {
-                    ty::TyBareFn(_, ref f) => f.sig.0.output.diverges(),
+                    ty::TyFnDef(_, ref f) | ty::TyFnPtr(ref f) => {
+                        f.sig.0.output.diverges()
+                    }
                     _ => false
                 };
                 let fun = unpack!(block = this.as_operand(block, fun));
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 1a8558b063a..801f4388ebd 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -61,7 +61,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     let method = method_callee(cx, self, ty::MethodCall::expr(self.id));
 
                     let sig = match method.ty.sty {
-                        ty::TyBareFn(_, fn_ty) => &fn_ty.sig,
+                        ty::TyFnDef(_, fn_ty) => &fn_ty.sig,
                         _ => cx.tcx.sess.span_bug(self.span, "type of method is not an fn")
                     };
 
@@ -625,7 +625,7 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
         Def::Struct(def_id) => match cx.tcx.node_id_to_type(expr.id).sty {
             // A tuple-struct constructor. Should only be reached if not called in the same
             // expression.
-            ty::TyBareFn(..) => (def_id, ItemKind::Function),
+            ty::TyFnDef(..) => (def_id, ItemKind::Function),
             // A unit struct which is used as a value. We return a completely different ExprKind
             // here to account for this special case.
             ty::TyStruct(adt_def, substs) => return ExprKind::Adt {
@@ -640,7 +640,7 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
         Def::Variant(enum_id, variant_id) => match cx.tcx.node_id_to_type(expr.id).sty {
             // A variant constructor. Should only be reached if not called in the same
             // expression.
-            ty::TyBareFn(..) => (variant_id, ItemKind::Function),
+            ty::TyFnDef(..) => (variant_id, ItemKind::Function),
             // A unit variant, similar special case to the struct case above.
             ty::TyEnum(adt_def, substs) => {
                 debug_assert!(adt_def.did == enum_id);
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index bf22c7b0b8b..96ea9c11e31 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -421,7 +421,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 let func_ty = mir.operand_ty(tcx, func);
                 debug!("check_terminator: call, func_ty={:?}", func_ty);
                 let func_ty = match func_ty.sty {
-                    ty::TyBareFn(_, func_ty) => func_ty,
+                    ty::TyFnDef(_, func_ty) | ty::TyFnPtr(func_ty) => func_ty,
                     _ => {
                         span_mirbug!(self, term, "call to non-function {:?}", func_ty);
                         return;
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 810712bb0cf..3a39a3c6dd1 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -582,7 +582,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                     v.add_qualif(ConstQualif::NON_ZERO_SIZED);
                 }
                 Some(Def::Struct(..)) => {
-                    if let ty::TyBareFn(..) = node_ty.sty {
+                    if let ty::TyFnDef(..) = node_ty.sty {
                         // Count the function pointer.
                         v.add_qualif(ConstQualif::NON_ZERO_SIZED);
                     }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 214ac81ee50..59518a97c6f 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -857,7 +857,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                 if let Def::Struct(..) = self.tcx.resolve_expr(expr) {
                     let expr_ty = self.tcx.expr_ty(expr);
                     let def = match expr_ty.sty {
-                        ty::TyBareFn(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
+                        ty::TyFnDef(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
                             output: ty::FnConverging(ty), ..
                         }), ..}) => ty,
                         _ => expr_ty
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index e8368f1bd97..c5508a8268f 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -451,8 +451,8 @@ fn find_discr_field_candidate<'tcx>(tcx: &TyCtxt<'tcx>,
         // Regular thin pointer: &T/&mut T/Box<T>
         ty::TyRef(..) | ty::TyBox(..) => Some(path),
 
-        // Functions are just pointers
-        ty::TyBareFn(..) => Some(path),
+        // Function pointer: `fn() -> i32`
+        ty::TyFnPtr(_) => Some(path),
 
         // Is this the NonZero lang item wrapping a pointer or integer type?
         ty::TyStruct(def, substs) if Some(def.did) == tcx.lang_items.non_zero() => {
diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs
index 8f9648b333b..d6dc7d45d2b 100644
--- a/src/librustc_trans/trans/attributes.rs
+++ b/src/librustc_trans/trans/attributes.rs
@@ -131,7 +131,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
 
     let function_type;
     let (fn_sig, abi, env_ty) = match fn_type.sty {
-        ty::TyBareFn(_, ref f) => (&f.sig, f.abi, None),
+        ty::TyFnDef(_, ref f) | ty::TyFnPtr(ref f) => (&f.sig, f.abi, None),
         ty::TyClosure(closure_did, ref substs) => {
             let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
             function_type = infcx.closure_type(closure_did, substs);
@@ -162,7 +162,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                 _ => ccx.sess().bug("expected tuple'd inputs")
             }
         },
-        ty::TyBareFn(..) if abi == Abi::RustCall => {
+        ty::TyFnDef(..) | ty::TyFnPtr(_) if abi == Abi::RustCall => {
             let mut inputs = vec![fn_sig.inputs[0]];
 
             match fn_sig.inputs[1].sty {
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 8f9608926b9..bd541067d14 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -390,7 +390,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 _ => bcx.sess().bug("compare_scalar_types: must be a comparison operator"),
             }
         }
-        ty::TyBareFn(..) | ty::TyBool | ty::TyUint(_) | ty::TyChar => {
+        ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyBool | ty::TyUint(_) | ty::TyChar => {
             ICmp(bcx,
                  bin_op_to_icmp_predicate(bcx.ccx(), op, false),
                  lhs,
@@ -906,7 +906,7 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                      -> ValueRef {
     let name = ccx.sess().cstore.item_symbol(did);
     match t.sty {
-        ty::TyBareFn(_, ref fn_ty) => {
+        ty::TyFnDef(_, ref fn_ty) => {
             match ccx.sess().target.target.adjust_abi(fn_ty.abi) {
                 Abi::Rust | Abi::RustCall => {
                     get_extern_rust_fn(ccx, t, &name[..], did)
@@ -2610,7 +2610,7 @@ fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                          node_id: ast::NodeId,
                          node_type: Ty<'tcx>)
                          -> ValueRef {
-    if let ty::TyBareFn(_, ref f) = node_type.sty {
+    if let ty::TyFnDef(_, ref f) = node_type.sty {
         if f.abi != Abi::Rust && f.abi != Abi::RustCall {
             ccx.sess().span_bug(sp,
                                 &format!("only the `{}` or `{}` calling conventions are valid \
@@ -2915,7 +2915,7 @@ fn register_method(ccx: &CrateContext,
 
     let sym = exported_name(ccx, id, mty, &attrs);
 
-    if let ty::TyBareFn(_, ref f) = mty.sty {
+    if let ty::TyFnDef(_, ref f) = mty.sty {
         let llfn = if f.abi == Abi::Rust || f.abi == Abi::RustCall {
             register_fn(ccx, span, sym, id, mty)
         } else {
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index 85660f1641d..c472e5fa62f 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -107,7 +107,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
                                 -> Callee<'blk, 'tcx> {
         let DatumBlock { bcx, datum, .. } = expr::trans(bcx, expr);
         match datum.ty.sty {
-            ty::TyBareFn(..) => {
+            ty::TyFnDef(..) | ty::TyFnPtr(_) => {
                 Callee {
                     bcx: bcx,
                     ty: datum.ty,
@@ -157,8 +157,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
                 }
             }
             Def::Fn(did) if match expr_ty.sty {
-                ty::TyBareFn(_, ref f) => f.abi == Abi::RustIntrinsic ||
-                                          f.abi == Abi::PlatformIntrinsic,
+                ty::TyFnDef(_, ref f) => f.abi == Abi::RustIntrinsic ||
+                                         f.abi == Abi::PlatformIntrinsic,
                 _ => false
             } => {
                 let substs = common::node_id_substs(bcx.ccx(),
@@ -292,11 +292,16 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
     // which is the fn pointer, and `args`, which is the arguments tuple.
     let (opt_def_id, sig) =
         match bare_fn_ty.sty {
-            ty::TyBareFn(opt_def_id,
-                           &ty::BareFnTy { unsafety: hir::Unsafety::Normal,
-                                           abi: Abi::Rust,
-                                           ref sig }) => {
-                (opt_def_id, sig)
+            ty::TyFnDef(def_id,
+                        &ty::BareFnTy { unsafety: hir::Unsafety::Normal,
+                                        abi: Abi::Rust,
+                                        ref sig }) => {
+                (Some(def_id), sig)
+            }
+            ty::TyFnPtr(&ty::BareFnTy { unsafety: hir::Unsafety::Normal,
+                                        abi: Abi::Rust,
+                                        ref sig }) => {
+                (None, sig)
             }
 
             _ => {
@@ -307,16 +312,20 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
     let sig = tcx.erase_late_bound_regions(sig);
     let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
     let tuple_input_ty = tcx.mk_tup(sig.inputs.to_vec());
-    let tuple_fn_ty = tcx.mk_fn(opt_def_id,
-        tcx.mk_bare_fn(ty::BareFnTy {
-            unsafety: hir::Unsafety::Normal,
-            abi: Abi::RustCall,
-            sig: ty::Binder(ty::FnSig {
-                inputs: vec![bare_fn_ty_maybe_ref,
-                             tuple_input_ty],
-                output: sig.output,
-                variadic: false
-            })}));
+    let bare_tuple_fn = ty::BareFnTy {
+        unsafety: hir::Unsafety::Normal,
+        abi: Abi::RustCall,
+        sig: ty::Binder(ty::FnSig {
+            inputs: vec![bare_fn_ty_maybe_ref,
+                         tuple_input_ty],
+            output: sig.output,
+            variadic: false
+        })
+    };
+    let tuple_fn_ty = match opt_def_id {
+        Some(def_id) => tcx.mk_fn_def(def_id, bare_tuple_fn),
+        None => tcx.mk_fn_ptr(bare_tuple_fn),
+    };
     debug!("tuple_fn_ty: {:?}", tuple_fn_ty);
 
     //
@@ -606,7 +615,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
     let mut bcx = callee.bcx;
 
     let (abi, ret_ty) = match callee.ty.sty {
-        ty::TyBareFn(_, ref f) => {
+        ty::TyFnDef(_, ref f) | ty::TyFnPtr(ref f) => {
             let sig = bcx.tcx().erase_late_bound_regions(&f.sig);
             let sig = infer::normalize_associated_type(bcx.tcx(), &sig);
             (f.abi, sig.output)
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index 0d9248a22b4..023ab02bc38 100644
--- a/src/librustc_trans/trans/closure.rs
+++ b/src/librustc_trans/trans/closure.rs
@@ -355,28 +355,31 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
     // Make a version with the type of by-ref closure.
     let ty::ClosureTy { unsafety, abi, mut sig } = infcx.closure_type(closure_def_id, &substs);
     sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
-    let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
-                                                               abi: abi,
-                                                               sig: sig.clone() });
-    let llref_fn_ty = tcx.mk_fn(None, llref_bare_fn_ty);
+    let llref_fn_ty = tcx.mk_fn_ptr(ty::BareFnTy {
+        unsafety: unsafety,
+        abi: abi,
+        sig: sig.clone()
+    });
     debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}",
            llref_fn_ty);
 
+    let ret_ty = tcx.erase_late_bound_regions(&sig.output());
+    let ret_ty = infer::normalize_associated_type(ccx.tcx(), &ret_ty);
+
     // Make a version of the closure type with the same arguments, but
     // with argument #0 being by value.
     assert_eq!(abi, RustCall);
     sig.0.inputs[0] = closure_ty;
-    let llonce_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
-                                                                abi: abi,
-                                                                sig: sig });
-    let llonce_fn_ty = tcx.mk_fn(None, llonce_bare_fn_ty);
+    let llonce_fn_ty = tcx.mk_fn_ptr(ty::BareFnTy {
+        unsafety: unsafety,
+        abi: abi,
+        sig: sig
+    });
 
     // Create the by-value helper.
     let function_name = link::mangle_internal_name_by_type_and_seq(ccx, llonce_fn_ty, "once_shim");
     let lloncefn = declare::define_internal_rust_fn(ccx, &function_name,
                                                     llonce_fn_ty);
-    let sig = tcx.erase_late_bound_regions(&llonce_bare_fn_ty.sig);
-    let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
 
     let (block_arena, fcx): (TypedArena<_>, FunctionContext);
     block_arena = TypedArena::new();
@@ -384,11 +387,11 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
                       lloncefn,
                       ast::DUMMY_NODE_ID,
                       false,
-                      sig.output,
+                      ret_ty,
                       substs.func_substs,
                       None,
                       &block_arena);
-    let mut bcx = init_function(&fcx, false, sig.output);
+    let mut bcx = init_function(&fcx, false, ret_ty);
 
     let llargs = get_params(fcx.llfn);
 
@@ -408,7 +411,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
 
     let dest =
         fcx.llretslotptr.get().map(
-            |_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot")));
+            |_| expr::SaveIn(fcx.get_ret_slot(bcx, ret_ty, "ret_slot")));
 
     let callee_data = TraitItem(MethodData { llfn: llreffn,
                                              llself: env_datum.val });
@@ -423,7 +426,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
 
     fcx.pop_and_trans_custom_cleanup_scope(bcx, self_scope);
 
-    finish_fn(&fcx, bcx, sig.output, DebugLoc::None);
+    finish_fn(&fcx, bcx, ret_ty, DebugLoc::None);
 
     lloncefn
 }
diff --git a/src/librustc_trans/trans/collector.rs b/src/librustc_trans/trans/collector.rs
index b5b0f0a82d4..14cbcb2086c 100644
--- a/src/librustc_trans/trans/collector.rs
+++ b/src/librustc_trans/trans/collector.rs
@@ -600,13 +600,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                                               def_id: DefId)
                                               -> bool {
             if !match ccx.tcx().lookup_item_type(def_id).ty.sty {
-                ty::TyBareFn(Some(def_id), _) => {
-                    // Some constructors also have type TyBareFn but they are
+                ty::TyFnDef(def_id, _) => {
+                    // Some constructors also have type TyFnDef but they are
                     // always instantiated inline and don't result in
-                    // translation item.
+                    // translation item. Same for FFI functions.
                     match ccx.tcx().map.get_if_local(def_id) {
                         Some(hir_map::NodeVariant(_))    |
-                        Some(hir_map::NodeStructCtor(_)) => false,
+                        Some(hir_map::NodeStructCtor(_)) |
+                        Some(hir_map::NodeForeignItem(_)) => false,
                         Some(_) => true,
                         None => {
                             ccx.sess().cstore.variant_kind(def_id).is_none()
@@ -697,17 +698,18 @@ fn find_drop_glue_neighbors<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     // Finally add the types of nested values
     match ty.sty {
-        ty::TyBool       |
-        ty::TyChar       |
-        ty::TyInt(_)     |
-        ty::TyUint(_)    |
-        ty::TyStr        |
-        ty::TyFloat(_)   |
-        ty::TyRawPtr(_)  |
-        ty::TyRef(..)    |
-        ty::TyBareFn(..) |
-        ty::TySlice(_)   |
-        ty::TyTrait(_)   => {
+        ty::TyBool      |
+        ty::TyChar      |
+        ty::TyInt(_)    |
+        ty::TyUint(_)   |
+        ty::TyStr       |
+        ty::TyFloat(_)  |
+        ty::TyRawPtr(_) |
+        ty::TyRef(..)   |
+        ty::TyFnDef(..) |
+        ty::TyFnPtr(_)  |
+        ty::TySlice(_)  |
+        ty::TyTrait(_)  => {
             /* nothing to do */
         }
         ty::TyStruct(ref adt_def, substs) |
@@ -1289,7 +1291,8 @@ pub fn push_unique_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                              &trait_data.bounds.projection_bounds,
                              output);
         },
-        ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
+        ty::TyFnDef(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) |
+        ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => {
             if unsafety == hir::Unsafety::Unsafe {
                 output.push_str("unsafe ");
             }
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 3ba27a4b787..5d8c5653b3e 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -1277,7 +1277,7 @@ pub fn inlined_variant_def<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     debug!("inlined_variant_def: ctor_ty={:?} inlined_vid={:?}", ctor_ty,
            inlined_vid);
     let adt_def = match ctor_ty.sty {
-        ty::TyBareFn(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
+        ty::TyFnDef(_, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
             output: ty::FnConverging(ty), ..
         }), ..}) => ty,
         _ => ctor_ty
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index 20da1583496..bec73c7cedc 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -917,7 +917,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     }
                 }
                 Def::Struct(..) => {
-                    if let ty::TyBareFn(..) = ety.sty {
+                    if let ty::TyFnDef(..) = ety.sty {
                         // Tuple struct.
                         expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
                     } else {
diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs
index 330d4077c41..895adb39708 100644
--- a/src/librustc_trans/trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/trans/debuginfo/metadata.rs
@@ -253,7 +253,8 @@ impl<'tcx> TypeMap<'tcx> {
                                        principal.substs,
                                        &mut unique_type_id);
             },
-            ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
+            ty::TyFnDef(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) |
+            ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => {
                 if unsafety == hir::Unsafety::Unsafe {
                     unique_type_id.push_str("unsafe ");
                 }
@@ -765,7 +766,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
             }
         }
-        ty::TyBareFn(_, ref barefnty) => {
+        ty::TyFnDef(_, ref barefnty) | ty::TyFnPtr(ref barefnty) => {
             let fn_metadata = subroutine_type_metadata(cx,
                                                        unique_type_id,
                                                        &barefnty.sig,
diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs
index 11dd631bee1..5052bece8c1 100644
--- a/src/librustc_trans/trans/debuginfo/mod.rs
+++ b/src/librustc_trans/trans/debuginfo/mod.rs
@@ -430,7 +430,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         let fn_type = monomorphize::apply_param_substs(cx.tcx(), param_substs, &fn_type);
 
         let (sig, abi) = match fn_type.sty {
-            ty::TyBareFn(_, ref barefnty) => {
+            ty::TyFnDef(_, ref barefnty) | ty::TyFnPtr(ref barefnty) => {
                 let sig = cx.tcx().erase_late_bound_regions(&barefnty.sig);
                 let sig = infer::normalize_associated_type(cx.tcx(), &sig);
                 (sig, barefnty.abi)
diff --git a/src/librustc_trans/trans/debuginfo/type_names.rs b/src/librustc_trans/trans/debuginfo/type_names.rs
index f243b1e3bfa..6539900cf3b 100644
--- a/src/librustc_trans/trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/trans/debuginfo/type_names.rs
@@ -101,7 +101,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             push_item_name(cx, principal.def_id, false, output);
             push_type_params(cx, principal.substs, output);
         },
-        ty::TyBareFn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
+        ty::TyFnDef(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) |
+        ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => {
             if unsafety == hir::Unsafety::Unsafe {
                 output.push_str("unsafe ");
             }
diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs
index 75b60be02f7..17278f3a140 100644
--- a/src/librustc_trans/trans/declare.rs
+++ b/src/librustc_trans/trans/declare.rs
@@ -106,7 +106,8 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
 
     let function_type; // placeholder so that the memory ownership works out ok
     let (sig, abi, env) = match fn_type.sty {
-        ty::TyBareFn(_, ref f) => {
+        ty::TyFnDef(_, f) |
+        ty::TyFnPtr(f) => {
             (&f.sig, f.abi, None)
         }
         ty::TyClosure(closure_did, ref substs) => {
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index e3e53607829..00ce0f81094 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -2525,7 +2525,7 @@ fn expr_kind(tcx: &TyCtxt, expr: &hir::Expr) -> ExprKind {
         hir::ExprPath(..) => {
             match tcx.resolve_expr(expr) {
                 Def::Struct(..) | Def::Variant(..) => {
-                    if let ty::TyBareFn(..) = tcx.node_id_to_type(expr.id).sty {
+                    if let ty::TyFnDef(..) = tcx.node_id_to_type(expr.id).sty {
                         // ctor function
                         ExprKind::RvalueDatum
                     } else {
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index 2a2178dd63b..805454df684 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -262,7 +262,8 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
            ccx.tn().val_to_string(llretptr));
 
     let (fn_abi, fn_sig) = match callee_ty.sty {
-        ty::TyBareFn(_, ref fn_ty) => (fn_ty.abi, &fn_ty.sig),
+        ty::TyFnDef(_, ref fn_ty) |
+        ty::TyFnPtr(ref fn_ty) => (fn_ty.abi, &fn_ty.sig),
         _ => ccx.sess().bug("trans_native_call called on non-function type")
     };
     let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
@@ -501,7 +502,8 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &hir::ForeignMod) {
                 abi => {
                     let ty = ccx.tcx().node_id_to_type(foreign_item.id);
                     match ty.sty {
-                        ty::TyBareFn(_, bft) => gate_simd_ffi(ccx.tcx(), &decl, bft),
+                        ty::TyFnDef(_, bft) |
+                        ty::TyFnPtr(bft) => gate_simd_ffi(ccx.tcx(), &decl, bft),
                         _ => ccx.tcx().sess.span_bug(foreign_item.span,
                                                      "foreign fn's sty isn't a bare_fn_ty?")
                     }
@@ -552,7 +554,7 @@ pub fn decl_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let tys = foreign_types_for_fn_ty(ccx, t);
     let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
     let cconv = match t.sty {
-        ty::TyBareFn(_, ref fn_ty) => {
+        ty::TyFnDef(_, ref fn_ty) | ty::TyFnPtr(ref fn_ty) => {
             llvm_calling_convention(ccx, fn_ty.abi)
         }
         _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi")
@@ -574,7 +576,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
 
     let t = ccx.tcx().node_id_to_type(node_id);
     let cconv = match t.sty {
-        ty::TyBareFn(_, ref fn_ty) => {
+        ty::TyFnDef(_, ref fn_ty) | ty::TyFnPtr(ref fn_ty) => {
             llvm_calling_convention(ccx, fn_ty.abi)
         }
         _ => panic!("expected bare fn in register_rust_fn_with_foreign_abi")
@@ -634,7 +636,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // Compute the type that the function would have if it were just a
         // normal Rust function. This will be the type of the wrappee fn.
         match t.sty {
-            ty::TyBareFn(_, ref f) => {
+            ty::TyFnDef(_, ref f) | ty::TyFnPtr(ref f)=> {
                 assert!(f.abi != Abi::Rust);
                 assert!(f.abi != Abi::RustIntrinsic);
                 assert!(f.abi != Abi::PlatformIntrinsic);
@@ -957,7 +959,7 @@ fn foreign_signature<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                      ty: Ty<'tcx>) -> ForeignTypes<'tcx> {
     let fn_sig = match ty.sty {
-        ty::TyBareFn(_, ref fn_ty) => &fn_ty.sig,
+        ty::TyFnDef(_, ref fn_ty) | ty::TyFnPtr(ref fn_ty) => &fn_ty.sig,
         _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type")
     };
     let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index b7b520f6c82..70c8681dbc1 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -1264,7 +1264,7 @@ fn get_rust_try_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
     // Define the type up front for the signature of the rust_try function.
     let tcx = ccx.tcx();
     let i8p = tcx.mk_mut_ptr(tcx.types.i8);
-    let fn_ty = tcx.mk_bare_fn(ty::BareFnTy {
+    let fn_ty = tcx.mk_fn_ptr(ty::BareFnTy {
         unsafety: hir::Unsafety::Unsafe,
         abi: Abi::Rust,
         sig: ty::Binder(ty::FnSig {
@@ -1273,9 +1273,8 @@ fn get_rust_try_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
             variadic: false,
         }),
     });
-    let fn_ty = tcx.mk_fn(None, fn_ty);
     let output = ty::FnOutput::FnConverging(tcx.types.i32);
-    let try_fn_ty  = tcx.mk_bare_fn(ty::BareFnTy {
+    let try_fn_ty  = ty::BareFnTy {
         unsafety: hir::Unsafety::Unsafe,
         abi: Abi::Rust,
         sig: ty::Binder(ty::FnSig {
@@ -1283,8 +1282,8 @@ fn get_rust_try_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
             output: output,
             variadic: false,
         }),
-    });
-    let rust_try = gen_fn(fcx, "__rust_try", tcx.mk_fn(None, try_fn_ty), output,
+    };
+    let rust_try = gen_fn(fcx, "__rust_try", tcx.mk_fn_ptr(try_fn_ty), output,
                           trans);
     *ccx.rust_try_fn().borrow_mut() = Some(rust_try);
     return rust_try
@@ -1353,7 +1352,7 @@ fn generate_filter_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
         // going on here, all I can say is that there's a few tests cases in
         // LLVM's test suite which follow this pattern of instructions, so we
         // just do the same.
-        let filter_fn_ty = tcx.mk_bare_fn(ty::BareFnTy {
+        let filter_fn_ty = tcx.mk_fn_ptr(ty::BareFnTy {
             unsafety: hir::Unsafety::Unsafe,
             abi: Abi::Rust,
             sig: ty::Binder(ty::FnSig {
@@ -1362,7 +1361,6 @@ fn generate_filter_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
                 variadic: false,
             }),
         });
-        let filter_fn_ty = tcx.mk_fn(None, filter_fn_ty);
         gen_fn(fcx, "__rustc_try_filter", filter_fn_ty, output, &mut |bcx| {
             let ebp = Call(bcx, frameaddress, &[C_i32(ccx, 1)], None, dloc);
             let exn = InBoundsGEP(bcx, ebp, &[C_i32(ccx, -20)]);
@@ -1373,7 +1371,7 @@ fn generate_filter_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
         // Conveniently on x86_64 the EXCEPTION_POINTERS handle and base pointer
         // are passed in as arguments to the filter function, so we just pass
         // those along.
-        let filter_fn_ty = tcx.mk_bare_fn(ty::BareFnTy {
+        let filter_fn_ty = tcx.mk_fn_ptr(ty::BareFnTy {
             unsafety: hir::Unsafety::Unsafe,
             abi: Abi::Rust,
             sig: ty::Binder(ty::FnSig {
@@ -1382,7 +1380,6 @@ fn generate_filter_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
                 variadic: false,
             }),
         });
-        let filter_fn_ty = tcx.mk_fn(None, filter_fn_ty);
         gen_fn(fcx, "__rustc_try_filter", filter_fn_ty, output, &mut |bcx| {
             let exn = llvm::get_param(bcx.fcx.llfn, 0);
             let rbp = llvm::get_param(bcx.fcx.llfn, 1);
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 221d17e6641..0898d2b4f9f 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -259,8 +259,8 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         traits::VtableObject(ref data) => {
             let idx = traits::get_vtable_index_of_object_method(bcx.tcx(), data, method_id);
             if let Some(self_expr) = self_expr {
-                if let ty::TyBareFn(_, ref fty) = monomorphize_type(bcx, method_ty).sty {
-                    let ty = bcx.tcx().mk_fn(None, opaque_method_ty(bcx.tcx(), fty));
+                if let ty::TyFnDef(_, ref fty) = monomorphize_type(bcx, method_ty).sty {
+                    let ty = opaque_method_ty(bcx.tcx(), fty);
                     return trans_trait_callee(bcx, ty, idx, self_expr, arg_cleanup_scope);
                 }
             }
@@ -401,19 +401,19 @@ pub fn trans_object_shim<'a, 'tcx>(
         }
     };
     let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty);
-    let fty = tcx.mk_bare_fn(fty);
-    let method_ty = opaque_method_ty(tcx, fty);
-    debug!("trans_object_shim: fty={:?} method_ty={:?}", fty, method_ty);
+
+    let ret_ty = ccx.tcx().erase_late_bound_regions(&fty.sig.output());
+    let ret_ty = infer::normalize_associated_type(ccx.tcx(), &ret_ty);
+
+    let method_fn_ty = opaque_method_ty(tcx, &fty);
+    let shim_fn_ty = tcx.mk_fn_ptr(fty);
+    debug!("trans_object_shim: shim_fn_ty={:?} method_fn_ty={:?}",
+           shim_fn_ty, method_fn_ty);
 
     //
-    let shim_fn_ty = tcx.mk_fn(None, fty);
-    let method_bare_fn_ty = tcx.mk_fn(None, method_ty);
     let function_name = link::mangle_internal_name_by_type_and_seq(ccx, shim_fn_ty, "object_shim");
     let llfn = declare::define_internal_rust_fn(ccx, &function_name, shim_fn_ty);
 
-    let sig = ccx.tcx().erase_late_bound_regions(&fty.sig);
-    let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
-
     let empty_substs = tcx.mk_substs(Substs::trans_empty());
     let (block_arena, fcx): (TypedArena<_>, FunctionContext);
     block_arena = TypedArena::new();
@@ -421,11 +421,11 @@ pub fn trans_object_shim<'a, 'tcx>(
                       llfn,
                       ast::DUMMY_NODE_ID,
                       false,
-                      sig.output,
+                      ret_ty,
                       empty_substs,
                       None,
                       &block_arena);
-    let mut bcx = init_function(&fcx, false, sig.output);
+    let mut bcx = init_function(&fcx, false, ret_ty);
 
     let llargs = get_params(fcx.llfn);
 
@@ -440,7 +440,7 @@ pub fn trans_object_shim<'a, 'tcx>(
 
     let dest =
         fcx.llretslotptr.get().map(
-            |_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot")));
+            |_| expr::SaveIn(fcx.get_ret_slot(bcx, ret_ty, "ret_slot")));
 
     debug!("trans_object_shim: method_offset_in_vtable={}",
            vtable_index);
@@ -448,13 +448,13 @@ pub fn trans_object_shim<'a, 'tcx>(
     bcx = trans_call_inner(bcx,
                            DebugLoc::None,
                            |bcx, _| trans_trait_callee_from_llval(bcx,
-                                                                  method_bare_fn_ty,
+                                                                  method_fn_ty,
                                                                   vtable_index,
                                                                   llself, llvtable),
                            ArgVals(&llargs[(self_idx + 2)..]),
                            dest).bcx;
 
-    finish_fn(&fcx, bcx, sig.output, DebugLoc::None);
+    finish_fn(&fcx, bcx, ret_ty, DebugLoc::None);
 
     immediate_rvalue(llfn, shim_fn_ty)
 }
@@ -642,11 +642,11 @@ pub fn get_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 /// Replace the self type (&Self or Box<Self>) with an opaque pointer.
 fn opaque_method_ty<'tcx>(tcx: &TyCtxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>)
-                          -> &'tcx ty::BareFnTy<'tcx> {
+                          -> Ty<'tcx> {
     let mut inputs = method_ty.sig.0.inputs.clone();
     inputs[0] = tcx.mk_mut_ptr(tcx.mk_mach_int(ast::IntTy::I8));
 
-    tcx.mk_bare_fn(ty::BareFnTy {
+    tcx.mk_fn_ptr(ty::BareFnTy {
         unsafety: method_ty.unsafety,
         abi: method_ty.abi,
         sig: ty::Binder(ty::FnSig {
diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs
index a9fee18ded8..0bbd32da049 100644
--- a/src/librustc_trans/trans/mir/block.rs
+++ b/src/librustc_trans/trans/mir/block.rs
@@ -37,17 +37,18 @@ enum AbiStyle {
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     fn abi_style(&self, fn_ty: Ty<'tcx>) -> AbiStyle {
-        if let ty::TyBareFn(_, ref f) = fn_ty.sty {
-            // We do not translate intrinsics here (they shouldn’t be functions)
-            assert!(f.abi != Abi::RustIntrinsic && f.abi != Abi::PlatformIntrinsic);
+        match fn_ty.sty {
+            ty::TyFnDef(_, ref f) | ty::TyFnPtr(ref f) => {
+                // We do not translate intrinsics here (they shouldn’t be functions)
+                assert!(f.abi != Abi::RustIntrinsic && f.abi != Abi::PlatformIntrinsic);
 
-            match f.abi {
-                Abi::Rust => AbiStyle::Rust,
-                Abi::RustCall => AbiStyle::RustCall,
-                _ => AbiStyle::Foreign
+                match f.abi {
+                    Abi::Rust => AbiStyle::Rust,
+                    Abi::RustCall => AbiStyle::RustCall,
+                    _ => AbiStyle::Foreign
+                }
             }
-        } else {
-            unreachable!()
+            _ => unreachable!()
         }
     }
 
diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs
index 24a7fd372f6..eed7ae6e72e 100644
--- a/src/librustc_trans/trans/type_of.rs
+++ b/src/librustc_trans/trans/type_of.rs
@@ -153,7 +153,7 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 // Given a function type and a count of ty params, construct an llvm type
 pub fn type_of_fn_from_ty<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fty: Ty<'tcx>) -> Type {
     match fty.sty {
-        ty::TyBareFn(_, ref f) => {
+        ty::TyFnDef(_, ref f) | ty::TyFnPtr(ref f) => {
             // FIXME(#19925) once fn item types are
             // zero-sized, we'll need to do something here
             if f.abi == Abi::Rust || f.abi == Abi::RustCall {
@@ -210,7 +210,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             }
         }
 
-        ty::TyBareFn(..) => Type::i8p(cx),
+        ty::TyFnDef(..) | ty::TyFnPtr(_) => Type::i8p(cx),
 
         ty::TyArray(ty, size) => {
             let llty = sizing_type_of(cx, ty);
@@ -415,7 +415,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
       ty::TySlice(ty) => in_memory_type_of(cx, ty),
       ty::TyStr | ty::TyTrait(..) => Type::i8(cx),
 
-      ty::TyBareFn(..) => {
+      ty::TyFnDef(..) | ty::TyFnPtr(_) => {
           type_of_fn_from_ty(cx, t).ptr_to()
       }
       ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx),
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 134da7a3bb0..1938fa75829 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1636,8 +1636,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
         }
         hir::TyBareFn(ref bf) => {
             require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
-            let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &bf.decl);
-            tcx.mk_fn(None, tcx.mk_bare_fn(bare_fn))
+            tcx.mk_fn_ptr(ty_of_bare_fn(this, bf.unsafety, bf.abi, &bf.decl))
         }
         hir::TyPolyTraitRef(ref bounds) => {
             conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds)
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 42ea3cc2aaa..f3bf7d895ea 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -130,7 +130,7 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
     // If the callee is a bare function or a closure, then we're all set.
     match structurally_resolved_type(fcx, callee_expr.span, adjusted_ty).sty {
-        ty::TyBareFn(..) => {
+        ty::TyFnDef(..) | ty::TyFnPtr(_) => {
             fcx.write_autoderef_adjustment(callee_expr.id, autoderefs);
             return Some(CallStep::Builtin);
         }
@@ -225,7 +225,8 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
     let error_fn_sig;
 
     let fn_sig = match callee_ty.sty {
-        ty::TyBareFn(_, &ty::BareFnTy {ref sig, ..}) => {
+        ty::TyFnDef(_, &ty::BareFnTy {ref sig, ..}) |
+        ty::TyFnPtr(&ty::BareFnTy {ref sig, ..}) => {
             sig
         }
         _ => {
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 5ab3c6f983f..c7184500159 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -141,13 +141,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         }
 
         match a.sty {
-            ty::TyBareFn(Some(_), a_f) => {
+            ty::TyFnDef(_, a_f) => {
                 // Function items are coercible to any closure
                 // type; function pointers are not (that would
                 // require double indirection).
                 self.coerce_from_fn_item(a, a_f, b)
             }
-            ty::TyBareFn(None, a_f) => {
+            ty::TyFnPtr(a_f) => {
                 // We permit coercion of fn pointers to drop the
                 // unsafe qualifier.
                 self.coerce_from_fn_pointer(a, a_f, b)
@@ -357,7 +357,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             debug!("coerce_from_fn_pointer(a={:?}, b={:?})",
                    a, b);
 
-            if let ty::TyBareFn(None, fn_ty_b) = b.sty {
+            if let ty::TyFnPtr(fn_ty_b) = b.sty {
                 match (fn_ty_a.unsafety, fn_ty_b.unsafety) {
                     (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
                         let unsafe_a = self.tcx().safe_to_unsafe_fn_ty(fn_ty_a);
@@ -386,8 +386,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                    a, b);
 
             match b.sty {
-                ty::TyBareFn(None, _) => {
-                    let a_fn_pointer = self.tcx().mk_fn(None, fn_ty_a);
+                ty::TyFnPtr(_) => {
+                    let a_fn_pointer = self.tcx().mk_ty(ty::TyFnPtr(fn_ty_a));
                     try!(self.subtype(a_fn_pointer, b));
                     Ok(Some(AdjustReifyFnPointer))
                 }
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 2bf7d65e331..ff7b809577f 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -276,9 +276,9 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
     // type.
 
     // Compute skolemized form of impl and trait method tys.
-    let impl_fty = tcx.mk_fn(None, tcx.mk_bare_fn(impl_m.fty.clone()));
+    let impl_fty = tcx.mk_fn_ptr(impl_m.fty.clone());
     let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs);
-    let trait_fty = tcx.mk_fn(None, tcx.mk_bare_fn(trait_m.fty.clone()));
+    let trait_fty = tcx.mk_fn_ptr(trait_m.fty.clone());
     let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
 
     let err = infcx.commit_if_ok(|snapshot| {
@@ -296,11 +296,11 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
                                                  impl_m_span,
                                                  impl_m_body_id,
                                                  &impl_sig);
-        let impl_fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
+        let impl_fty = tcx.mk_fn_ptr(ty::BareFnTy {
             unsafety: impl_m.fty.unsafety,
             abi: impl_m.fty.abi,
             sig: ty::Binder(impl_sig)
-        }));
+        });
         debug!("compare_impl_method: impl_fty={:?}",
                impl_fty);
 
@@ -314,11 +314,11 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
                                                  impl_m_span,
                                                  impl_m_body_id,
                                                  &trait_sig);
-        let trait_fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
+        let trait_fty = tcx.mk_fn_ptr(ty::BareFnTy {
             unsafety: trait_m.fty.unsafety,
             abi: trait_m.fty.abi,
             sig: ty::Binder(trait_sig)
-        }));
+        });
 
         debug!("compare_impl_method: trait_fty={:?}",
                trait_fty);
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 78faef473dd..4ebe4c25dd1 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -479,7 +479,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
             Ok(())
         }
 
-        ty::TyBareFn(..) => {
+        ty::TyFnDef(..) | ty::TyFnPtr(_) => {
             // FIXME(#26656): this type is always destruction-safe, but
             // it implicitly witnesses Self: Fn, which can be false.
             Ok(())
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 6d8fff3caca..525e4888fdb 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -33,7 +33,8 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: &TyCtxt<'tcx>, it: &hir::ForeignItem,
                                    abi: Abi,
                                    inputs: Vec<ty::Ty<'tcx>>,
                                    output: ty::FnOutput<'tcx>) {
-    let fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
+    let def_id = tcx.map.local_def_id(it.id);
+    let fty = tcx.mk_fn_def(def_id, ty::BareFnTy {
         unsafety: hir::Unsafety::Unsafe,
         abi: abi,
         sig: ty::Binder(FnSig {
@@ -41,8 +42,8 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: &TyCtxt<'tcx>, it: &hir::ForeignItem,
             output: output,
             variadic: false,
         }),
-    }));
-    let i_ty = tcx.lookup_item_type(tcx.map.local_def_id(it.id));
+    });
+    let i_ty = tcx.lookup_item_type(def_id);
     let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
     if i_n_tps != n_tps {
         span_err!(tcx.sess, it.span, E0094,
@@ -296,8 +297,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
                         variadic: false,
                     }),
                 };
-                let fn_ty = tcx.mk_bare_fn(fn_ty);
-                (0, vec![tcx.mk_fn(None, fn_ty), mut_u8, mut_u8], tcx.types.i32)
+                (0, vec![tcx.mk_fn_ptr(fn_ty), mut_u8, mut_u8], tcx.types.i32)
             }
 
             ref other => {
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index f2f2eb66444..6b00beb5f39 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -105,11 +105,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
 
         // Create the method type
         let method_ty = pick.item.as_opt_method().unwrap();
-        let fty = self.tcx().mk_fn(None, self.tcx().mk_bare_fn(ty::BareFnTy {
+        let fty = self.tcx().mk_fn_ptr(ty::BareFnTy {
             sig: ty::Binder(method_sig),
             unsafety: method_ty.fty.unsafety,
             abi: method_ty.fty.abi.clone(),
-        }));
+        });
 
         // Add any trait/regions obligations specified on the method's type parameters.
         self.add_obligations(fty, &all_substs, &method_predicates);
@@ -457,7 +457,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
     fn fixup_derefs_on_method_receiver_if_necessary(&self,
                                                     method_callee: &ty::MethodCallee) {
         let sig = match method_callee.ty.sty {
-            ty::TyBareFn(_, ref f) => f.sig.clone(),
+            ty::TyFnPtr(ref f) => f.sig.clone(),
             _ => return,
         };
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index fce44683413..f86034d9aff 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -230,11 +230,11 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                                        &method_ty.fty.sig).0;
     let fn_sig = fcx.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
     let transformed_self_ty = fn_sig.inputs[0];
-    let fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
+    let fty = tcx.mk_fn_ptr(ty::BareFnTy {
         sig: ty::Binder(fn_sig),
         unsafety: method_ty.fty.unsafety,
         abi: method_ty.fty.abi.clone(),
-    }));
+    });
 
     debug!("lookup_in_trait_adjusted: matched method fty={:?} obligation={:?}",
            fty,
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index e7d84efdaa2..e6336696663 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -101,7 +101,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     match field_ty.sty {
                         // Not all of these (e.g. unsafe fns) implement FnOnce
                         // so we look for these beforehand
-                        ty::TyClosure(..) | ty::TyBareFn(..) => {
+                        ty::TyClosure(..) | ty::TyFnDef(..) | ty::TyFnPtr(_) => {
                             span_stored_function!();
                         }
                         // If it's not a simple function, look for things which implement FnOnce
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index eee3d232831..acac32fe38c 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -434,7 +434,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            param_env: ty::ParameterEnvironment<'a, 'tcx>)
 {
     match raw_fty.sty {
-        ty::TyBareFn(_, ref fn_ty) => {
+        ty::TyFnDef(_, ref fn_ty) => {
             let tables = RefCell::new(ty::Tables::empty());
             let inh = Inherited::new(ccx.tcx, &tables, param_env);
 
@@ -2340,7 +2340,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         ty::FnConverging(fcx.tcx().types.err)
     } else {
         match method_fn_ty.sty {
-            ty::TyBareFn(_, ref fty) => {
+            ty::TyFnPtr(ref fty) => {
                 // HACK(eddyb) ignore self in the definition (see above).
                 let expected_arg_tys = expected_types_for_fn_args(fcx,
                                                                   sp,
@@ -2619,7 +2619,7 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     ty::TyInt(_) | ty::TyUint(_) => Some(ty),
                     ty::TyChar => Some(tcx.types.u8),
                     ty::TyRawPtr(..) => Some(tcx.types.usize),
-                    ty::TyBareFn(..) => Some(tcx.types.usize),
+                    ty::TyFnDef(..) | ty::TyFnPtr(_) => Some(tcx.types.usize),
                     _ => None
                 }
             });
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index f6225cf6ca7..e428fc927f0 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -881,7 +881,7 @@ fn constrain_callee(rcx: &mut Rcx,
                     _callee_expr: &hir::Expr) {
     let callee_ty = rcx.resolve_node_type(callee_id);
     match callee_ty.sty {
-        ty::TyBareFn(..) => { }
+        ty::TyFnDef(..) | ty::TyFnPtr(_) => { }
         _ => {
             // this should not happen, but it does if the program is
             // erroneous
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 997f56bd449..5aa810c7e41 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -255,9 +255,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             let type_scheme = fcx.tcx().lookup_item_type(fcx.tcx().map.local_def_id(item.id));
             let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &type_scheme.ty);
             let bare_fn_ty = match item_ty.sty {
-                ty::TyBareFn(_, ref bare_fn_ty) => bare_fn_ty,
+                ty::TyFnDef(_, ref bare_fn_ty) => bare_fn_ty,
                 _ => {
-                    this.tcx().sess.span_bug(item.span, "Fn item without bare fn type");
+                    this.tcx().sess.span_bug(item.span, "Fn item without fn type");
                 }
             };
 
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 61060114330..28fbaf21367 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -27,7 +27,7 @@ use middle::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
 use middle::ty::{TyParam, TyRawPtr};
 use middle::ty::{TyRef, TyStruct, TyTrait, TyTuple};
 use middle::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
-use middle::ty::{TyUint, TyClosure, TyBox, TyBareFn};
+use middle::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr};
 use middle::ty::TyProjection;
 use middle::ty::util::CopyImplementationError;
 use middle::free_region::FreeRegionMap;
@@ -67,8 +67,8 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
         }
 
         TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-        TyStr | TyArray(..) | TySlice(..) | TyBareFn(..) | TyTuple(..) |
-        TyParam(..) | TyError |
+        TyStr | TyArray(..) | TySlice(..) | TyFnDef(..) | TyFnPtr(_) |
+        TyTuple(..) | TyParam(..) | TyError |
         TyRawPtr(_) | TyRef(_, _) | TyProjection(..) => {
             None
         }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index b3305fdb9a0..ab781ea57d4 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -552,8 +552,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     def_id,
                                     container);
 
-    let fty = ccx.tcx.mk_fn(Some(def_id),
-                            ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
+    let fty = ccx.tcx.mk_fn_def(def_id, ty_method.fty.clone());
     debug!("method {} (id {}) has type {:?}",
             name, id, fty);
     ccx.tcx.register_item_type(def_id, TypeScheme {
@@ -1436,7 +1435,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
             let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
             let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl);
-            let ty = tcx.mk_fn(Some(ccx.tcx.map.local_def_id(it.id)), tcx.mk_bare_fn(tofd));
+            let ty = tcx.mk_fn_def(ccx.tcx.map.local_def_id(it.id), tofd);
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
         hir::ItemTy(ref t, ref generics) => {
@@ -1556,7 +1555,9 @@ fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
 {
     match it.node {
         hir::ForeignItemFn(ref fn_decl, ref generics) => {
-            compute_type_scheme_of_foreign_fn_decl(ccx, fn_decl, generics, abi)
+            compute_type_scheme_of_foreign_fn_decl(
+                ccx, ccx.tcx.map.local_def_id(it.id),
+                fn_decl, generics, abi)
         }
         hir::ForeignItemStatic(ref t, _) => {
             ty::TypeScheme {
@@ -2107,6 +2108,7 @@ fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
 
 fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
     ccx: &CrateCtxt<'a, 'tcx>,
+    id: DefId,
     decl: &hir::FnDecl,
     ast_generics: &hir::Generics,
     abi: abi::Abi)
@@ -2140,14 +2142,13 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
             ty::FnDiverging
     };
 
-    let t_fn = ccx.tcx.mk_fn(None,
-        ccx.tcx.mk_bare_fn(ty::BareFnTy {
-            abi: abi,
-            unsafety: hir::Unsafety::Unsafe,
-            sig: ty::Binder(ty::FnSig {inputs: input_tys,
-                                       output: output,
-                                       variadic: decl.variadic}),
-        }));
+    let t_fn = ccx.tcx.mk_fn_def(id, ty::BareFnTy {
+        abi: abi,
+        unsafety: hir::Unsafety::Unsafe,
+        sig: ty::Binder(ty::FnSig {inputs: input_tys,
+                                    output: output,
+                                    variadic: decl.variadic}),
+    });
 
     ty::TypeScheme {
         generics: ty_generics,
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index 336bff26e2c..907ee15c41b 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -72,7 +72,8 @@ fn parameters_for_type_shallow<'tcx>(ty: Ty<'tcx>) -> Vec<Parameter> {
             parameters_for_regions_in_substs(&pi.trait_ref.substs),
         ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
         ty::TyFloat(..) | ty::TyBox(..) | ty::TyStr |
-        ty::TyArray(..) | ty::TySlice(..) | ty::TyBareFn(..) |
+        ty::TyArray(..) | ty::TySlice(..) |
+        ty::TyFnDef(..) | ty::TyFnPtr(_) |
         ty::TyTuple(..) | ty::TyRawPtr(..) |
         ty::TyInfer(..) | ty::TyClosure(..) | ty::TyError =>
             vec![]
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index a103cbc928b..d986d19e0f0 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -220,7 +220,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
     let tcx = ccx.tcx;
     let main_t = tcx.node_id_to_type(main_id);
     match main_t.sty {
-        ty::TyBareFn(..) => {
+        ty::TyFnDef(..) => {
             match tcx.map.find(main_id) {
                 Some(hir_map::NodeItem(it)) => {
                     match it.node {
@@ -236,7 +236,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 _ => ()
             }
             let main_def_id = tcx.map.local_def_id(main_id);
-            let se_ty = tcx.mk_fn(Some(main_def_id), tcx.mk_bare_fn(ty::BareFnTy {
+            let se_ty = tcx.mk_fn_def(main_def_id, ty::BareFnTy {
                 unsafety: hir::Unsafety::Normal,
                 abi: Abi::Rust,
                 sig: ty::Binder(ty::FnSig {
@@ -244,7 +244,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                     output: ty::FnConverging(tcx.mk_nil()),
                     variadic: false
                 })
-            }));
+            });
 
             require_same_types(tcx, None, false, main_span, main_t, se_ty,
                 || {
@@ -266,7 +266,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
     let tcx = ccx.tcx;
     let start_t = tcx.node_id_to_type(start_id);
     match start_t.sty {
-        ty::TyBareFn(..) => {
+        ty::TyFnDef(..) => {
             match tcx.map.find(start_id) {
                 Some(hir_map::NodeItem(it)) => {
                     match it.node {
@@ -282,8 +282,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 _ => ()
             }
 
-            let se_ty = tcx.mk_fn(Some(ccx.tcx.map.local_def_id(start_id)),
-                                  tcx.mk_bare_fn(ty::BareFnTy {
+            let se_ty = tcx.mk_fn_def(ccx.tcx.map.local_def_id(start_id), ty::BareFnTy {
                 unsafety: hir::Unsafety::Normal,
                 abi: Abi::Rust,
                 sig: ty::Binder(ty::FnSig {
@@ -294,7 +293,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                     output: ty::FnConverging(tcx.types.isize),
                     variadic: false,
                 }),
-            }));
+            });
 
             require_same_types(tcx, None, false, start_span, start_t, se_ty,
                 || {
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 0c9fa9fd0ab..8e24a5cc1ea 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -429,7 +429,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 }
             }
 
-            ty::TyBareFn(_, &ty::BareFnTy { ref sig, .. }) => {
+            ty::TyFnDef(_, &ty::BareFnTy { ref sig, .. }) |
+            ty::TyFnPtr(&ty::BareFnTy { ref sig, .. }) => {
                 self.add_constraints_from_sig(generics, sig, variance);
             }
 
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 32f3706675a..90cdd7e5833 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -164,7 +164,7 @@ pub fn build_external_trait(cx: &DocContext, tcx: &TyCtxt,
 fn build_external_function(cx: &DocContext, tcx: &TyCtxt, did: DefId) -> clean::Function {
     let t = tcx.lookup_item_type(did);
     let (decl, style, abi) = match t.ty.sty {
-        ty::TyBareFn(_, ref f) => ((did, &f.sig).clean(cx), f.unsafety, f.abi),
+        ty::TyFnDef(_, ref f) => ((did, &f.sig).clean(cx), f.unsafety, f.abi),
         _ => panic!("bad function"),
     };
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 6c9ee528782..579bef0ec9c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1663,7 +1663,8 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                 mutability: mt.mutbl.clean(cx),
                 type_: box mt.ty.clean(cx),
             },
-            ty::TyBareFn(_, ref fty) => BareFunction(box BareFunctionDecl {
+            ty::TyFnDef(_, ref fty) |
+            ty::TyFnPtr(ref fty) => BareFunction(box BareFunctionDecl {
                 unsafety: fty.unsafety,
                 generics: Generics {
                     lifetimes: Vec::new(),
diff --git a/src/test/auxiliary/issue13507.rs b/src/test/auxiliary/issue13507.rs
index 78d0394a6e5..4cb846b5186 100644
--- a/src/test/auxiliary/issue13507.rs
+++ b/src/test/auxiliary/issue13507.rs
@@ -14,26 +14,26 @@ pub mod testtypes {
     use std::any::TypeId;
 
     pub fn type_ids() -> Vec<TypeId> {
-        let mut ids = vec!();
-        ids.push(TypeId::of::<FooNil>());
-        ids.push(TypeId::of::<FooBool>());
-        ids.push(TypeId::of::<FooInt>());
-        ids.push(TypeId::of::<FooUint>());
-        ids.push(TypeId::of::<FooFloat>());
-        ids.push(TypeId::of::<FooEnum>());
-        ids.push(TypeId::of::<FooUniq>());
-        ids.push(TypeId::of::<FooPtr>());
-        ids.push(TypeId::of::<&'static FooTrait>());
-        ids.push(TypeId::of::<FooStruct>());
-        ids.push(TypeId::of::<FooTuple>());
-        ids
+        vec![
+            TypeId::of::<FooBool>(),
+            TypeId::of::<FooInt>(),
+            TypeId::of::<FooUint>(),
+            TypeId::of::<FooFloat>(),
+            TypeId::of::<FooStr>(),
+            TypeId::of::<FooArray>(),
+            TypeId::of::<FooSlice>(),
+            TypeId::of::<FooBox>(),
+            TypeId::of::<FooPtr>(),
+            TypeId::of::<FooRef>(),
+            TypeId::of::<FooFnPtr>(),
+            TypeId::of::<FooNil>(),
+            TypeId::of::<FooTuple>(),
+            TypeId::of::<FooTrait>(),
+            TypeId::of::<FooStruct>(),
+            TypeId::of::<FooEnum>()
+        ]
     }
 
-    // Tests ty_nil
-    pub type FooNil = ();
-
-    // Skipping ty_bot
-
     // Tests TyBool
     pub type FooBool = bool;
 
@@ -49,25 +49,26 @@ pub mod testtypes {
     // Tests TyFloat (does not test all variants of FloatTy)
     pub type FooFloat = f64;
 
-    // For TyStr, what kind of string should I use? &'static str? String? Raw str?
+    // Tests TyStr
+    pub type FooStr = str;
 
-    // Tests TyEnum
-    pub enum FooEnum {
-        VarA(usize),
-        VarB(usize, usize)
-    }
+    // Tests TyArray
+    pub type FooArray = [u8; 1];
 
-    // Tests TyBox (of u8)
-    pub type FooUniq = Box<u8>;
+    // Tests TySlice
+    pub type FooSlice = [u8];
 
-    // As with TyStr, what type should be used for TyArray?
+    // Tests TyBox (of u8)
+    pub type FooBox = Box<u8>;
 
     // Tests TyRawPtr
     pub type FooPtr = *const u8;
 
-    // Skipping TyRef
+    // Tests TyRef
+    pub type FooRef = &'static u8;
 
-    // Skipping TyBareFn (how do you get a bare function type, rather than proc or closure?)
+    // Tests TyFnPtr
+    pub type FooFnPtr = fn(u8) -> bool;
 
     // Tests TyTrait
     pub trait FooTrait {
@@ -80,14 +81,17 @@ pub mod testtypes {
         foo_field: usize
     }
 
+    // Tests TyEnum
+    pub enum FooEnum {
+        VarA(usize),
+        VarB(usize, usize)
+    }
+
     // Tests TyTuple
+    pub type FooNil = ();
     pub type FooTuple = (u8, i8, bool);
 
-    // Skipping ty_param
-
-    // Skipping ty_self
-
-    // Skipping ty_self
+    // Skipping TyParam
 
     // Skipping TyInfer
 
diff --git a/src/test/compile-fail/invalid-intrinsic.rs b/src/test/compile-fail/invalid-intrinsic.rs
new file mode 100644
index 00000000000..2aa2546cb9f
--- /dev/null
+++ b/src/test/compile-fail/invalid-intrinsic.rs
@@ -0,0 +1,16 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(intrinsics)]
+extern "rust-intrinsic" {
+    pub static breakpoint : unsafe extern "rust-intrinsic" fn();
+    //~^ ERROR intrinsic has wrong type
+}
+fn main() { unsafe { breakpoint(); } }
\ No newline at end of file
diff --git a/src/test/compile-fail/variadic-ffi-3.rs b/src/test/compile-fail/variadic-ffi-3.rs
index 94055450bc6..1d5ebdbae3e 100644
--- a/src/test/compile-fail/variadic-ffi-3.rs
+++ b/src/test/compile-fail/variadic-ffi-3.rs
@@ -22,7 +22,7 @@ fn main() {
         let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
         //~^ ERROR: mismatched types
         //~| expected `unsafe extern "C" fn(isize, u8)`
-        //~| found `unsafe extern "C" fn(isize, u8, ...)`
+        //~| found `unsafe extern "C" fn(isize, u8, ...) {foo}`
         //~| expected non-variadic fn
         //~| found variadic function
 
diff --git a/src/test/run-pass/issue-13507-2.rs b/src/test/run-pass/issue-13507-2.rs
index 91ec3e85404..084b7a166cd 100644
--- a/src/test/run-pass/issue-13507-2.rs
+++ b/src/test/run-pass/issue-13507-2.rs
@@ -19,23 +19,29 @@ use issue13507::testtypes;
 use std::any::TypeId;
 
 pub fn type_ids() -> Vec<TypeId> {
-    let mut ids = vec!();
-    ids.push(TypeId::of::<testtypes::FooNil>());
-    ids.push(TypeId::of::<testtypes::FooBool>());
-    ids.push(TypeId::of::<testtypes::FooInt>());
-    ids.push(TypeId::of::<testtypes::FooUint>());
-    ids.push(TypeId::of::<testtypes::FooFloat>());
-    ids.push(TypeId::of::<testtypes::FooEnum>());
-    ids.push(TypeId::of::<testtypes::FooUniq>());
-    ids.push(TypeId::of::<testtypes::FooPtr>());
-    ids.push(TypeId::of::<&'static testtypes::FooTrait>());
-    ids.push(TypeId::of::<testtypes::FooStruct>());
-    ids.push(TypeId::of::<testtypes::FooTuple>());
-    ids
+    use issue13507::testtypes::*;
+    vec![
+        TypeId::of::<FooBool>(),
+        TypeId::of::<FooInt>(),
+        TypeId::of::<FooUint>(),
+        TypeId::of::<FooFloat>(),
+        TypeId::of::<FooStr>(),
+        TypeId::of::<FooArray>(),
+        TypeId::of::<FooSlice>(),
+        TypeId::of::<FooBox>(),
+        TypeId::of::<FooPtr>(),
+        TypeId::of::<FooRef>(),
+        TypeId::of::<FooFnPtr>(),
+        TypeId::of::<FooNil>(),
+        TypeId::of::<FooTuple>(),
+        TypeId::of::<FooTrait>(),
+        TypeId::of::<FooStruct>(),
+        TypeId::of::<FooEnum>()
+    ]
 }
 
 pub fn main() {
-    let othercrate = testtypes::type_ids();
+    let othercrate = issue13507::testtypes::type_ids();
     let thiscrate = type_ids();
     assert_eq!(thiscrate, othercrate);
 }