about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-11-26 06:36:09 -0500
committerNiko Matsakis <niko@alum.mit.edu>2014-12-22 12:27:07 -0500
commitf46099575a304ae9032f45c7921b496c4d220697 (patch)
tree7631fb43337868e152aafb545493d482a8981994
parent8c8cb997a592f7348958e58c98117be03764d8b0 (diff)
downloadrust-f46099575a304ae9032f45c7921b496c4d220697.tar.gz
rust-f46099575a304ae9032f45c7921b496c4d220697.zip
Make ty_bare_fn carry an optional def-id indicating whether it is the
type of a fn item or a fn pointer, which are now differentiated.
Introduce coercion from fn item to fn pointer.
-rw-r--r--src/librustc/middle/check_const.rs6
-rw-r--r--src/librustc/middle/expr_use_visitor.rs10
-rw-r--r--src/librustc/middle/infer/coercion.rs60
-rw-r--r--src/librustc/middle/infer/combine.rs11
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/middle/ty.rs60
-rw-r--r--src/librustc/middle/ty_fold.rs4
-rw-r--r--src/librustc_trans/trans/base.rs1
-rw-r--r--src/librustc_trans/trans/callee.rs5
-rw-r--r--src/librustc_trans/trans/closure.rs22
-rw-r--r--src/librustc_trans/trans/consts.rs7
-rw-r--r--src/librustc_trans/trans/expr.rs11
-rw-r--r--src/librustc_trans/trans/glue.rs1
-rw-r--r--src/librustc_trans/trans/meth.rs3
-rw-r--r--src/librustc_typeck/astconv.rs2
-rw-r--r--src/librustc_typeck/check/method/confirm.rs2
-rw-r--r--src/librustc_typeck/check/method/mod.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs16
-rw-r--r--src/librustc_typeck/check/writeback.rs24
-rw-r--r--src/librustc_typeck/coherence/mod.rs2
-rw-r--r--src/librustc_typeck/collect.rs17
-rw-r--r--src/librustc_typeck/lib.rs5
22 files changed, 161 insertions, 114 deletions
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index a91ea8bfef8..e08dd64d4d4 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -127,7 +127,11 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
         ast::ExprCast(ref from, _) => {
             let toty = ty::expr_ty(v.tcx, e);
             let fromty = ty::expr_ty(v.tcx, &**from);
-            if !ty::type_is_numeric(toty) && !ty::type_is_unsafe_ptr(toty) {
+            let is_legal_cast =
+                ty::type_is_numeric(toty) ||
+                ty::type_is_unsafe_ptr(toty) ||
+                (ty::type_is_bare_fn(toty) && ty::type_is_bare_fn_item(fromty));
+            if !is_legal_cast {
                 span_err!(v.tcx.sess, e.span, E0012,
                           "can not cast to `{}` in a constant expression",
                           ppaux::ty_to_string(v.tcx, toty));
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index abc3c8d0d8f..046a2894b5d 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -824,10 +824,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             None => { }
             Some(adjustment) => {
                 match *adjustment {
-                    ty::AdjustAddEnv(..) => {
-                        // Creating a closure consumes the input and stores it
-                        // into the resulting rvalue.
-                        debug!("walk_adjustment(AutoAddEnv)");
+                    ty::AdjustAddEnv(..) |
+                    ty::AdjustReifyFnPointer(..) => {
+                        // Creating a closure/fn-pointer consumes the
+                        // input and stores it into the resulting
+                        // rvalue.
+                        debug!("walk_adjustment(AutoAddEnv|AdjustReifyFnPointer)");
                         let cmt_unadjusted =
                             return_if_err!(self.mc.cat_expr_unadjusted(expr));
                         self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
diff --git a/src/librustc/middle/infer/coercion.rs b/src/librustc/middle/infer/coercion.rs
index ca9ac10341c..08336da0d8a 100644
--- a/src/librustc/middle/infer/coercion.rs
+++ b/src/librustc/middle/infer/coercion.rs
@@ -486,8 +486,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                b.repr(self.tcx()));
 
         match a.sty {
-            ty::ty_bare_fn(ref f) => {
-                self.coerce_from_bare_fn(a, f, b)
+            ty::ty_bare_fn(Some(a_def_id), ref f) => {
+                self.coerce_from_fn_item(a, a_def_id, f, b)
             }
             _ => {
                 self.subtype(a, b)
@@ -495,32 +495,46 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         }
     }
 
-    ///  Attempts to coerce from a bare Rust function (`extern "Rust" fn`) into a closure or a
-    ///  `proc`.
-    fn coerce_from_bare_fn(&self, a: Ty<'tcx>, fn_ty_a: &ty::BareFnTy<'tcx>, b: Ty<'tcx>)
+    fn coerce_from_fn_item(&self,
+                           a: Ty<'tcx>,
+                           fn_def_id_a: ast::DefId,
+                           fn_ty_a: &ty::BareFnTy<'tcx>,
+                           b: Ty<'tcx>)
                            -> CoerceResult<'tcx> {
-        self.unpack_actual_value(b, |b| {
+        /*!
+         * Attempts to coerce from the type of a Rust function item
+         * into a closure or a `proc`.
+         */
 
+        self.unpack_actual_value(b, |b| {
             debug!("coerce_from_bare_fn(a={}, b={})",
-                   a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx));
+                   a.repr(self.tcx()), b.repr(self.tcx()));
 
-            if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal {
-                return self.subtype(a, b);
-            }
+            match b.sty {
+                ty::ty_closure(ref f) => {
+                    if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal {
+                        return self.subtype(a, b);
+                    }
 
-            let fn_ty_b = match b.sty {
-                ty::ty_closure(ref f) => (*f).clone(),
-                _ => return self.subtype(a, b)
-            };
-
-            let adj = ty::AdjustAddEnv(fn_ty_b.store);
-            let a_closure = ty::mk_closure(self.get_ref().infcx.tcx,
-                                           ty::ClosureTy {
-                                                sig: fn_ty_a.sig.clone(),
-                                                .. *fn_ty_b
-                                           });
-            try!(self.subtype(a_closure, b));
-            Ok(Some(adj))
+                    let fn_ty_b = (*f).clone();
+                    let adj = ty::AdjustAddEnv(fn_def_id_a, fn_ty_b.store);
+                    let a_closure = ty::mk_closure(self.tcx(),
+                                                   ty::ClosureTy {
+                                                       sig: fn_ty_a.sig.clone(),
+                                                       .. *fn_ty_b
+                                                   });
+                    try!(self.subtype(a_closure, b));
+                    Ok(Some(adj))
+                }
+                ty::ty_bare_fn(None, _) => {
+                    let a_fn_pointer = ty::mk_bare_fn(self.tcx(), None, (*fn_ty_a).clone());
+                    try!(self.subtype(a_fn_pointer, b));
+                    Ok(Some(ty::AdjustReifyFnPointer(fn_def_id_a)))
+                }
+                _ => {
+                    return self.subtype(a, b)
+                }
+            }
         })
     }
 
diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs
index 82ddbcee5a7..fc240faac44 100644
--- a/src/librustc/middle/infer/combine.rs
+++ b/src/librustc/middle/infer/combine.rs
@@ -568,11 +568,12 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
         }
       }
 
-      (&ty::ty_bare_fn(ref a_fty), &ty::ty_bare_fn(ref b_fty)) => {
-        this.bare_fn_tys(a_fty, b_fty).and_then(|fty| {
-            Ok(ty::mk_bare_fn(tcx, fty))
-        })
-      }
+        (&ty::ty_bare_fn(a_opt_def_id, ref a_fty), &ty::ty_bare_fn(b_opt_def_id, ref b_fty))
+            if a_opt_def_id == b_opt_def_id =>
+        {
+            let fty = try!(this.bare_fn_tys(a_fty, b_fty));
+            Ok(ty::mk_bare_fn(tcx, a_opt_def_id, fty))
+        }
 
       (&ty::ty_closure(ref a_fty), &ty::ty_closure(ref b_fty)) => {
         this.closure_tys(&**a_fty, &**b_fty).and_then(|fty| {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index dce75579ca0..5aac988948f 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -441,8 +441,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
 
             Some(adjustment) => {
                 match *adjustment {
-                    ty::AdjustAddEnv(..) => {
-                        debug!("cat_expr(AdjustAddEnv): {}",
+                    ty::AdjustAddEnv(..) | ty::AdjustReifyFnPointer(..) => {
+                        debug!("cat_expr(AdjustAddEnv|AdjustReifyFnPointer): {}",
                                expr.repr(self.tcx()));
                         // Convert a bare fn to a closure by adding NULL env.
                         // Result is an rvalue.
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 50a6fb9d0ca..4130d07aed0 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -293,7 +293,8 @@ pub enum Variance {
 
 #[deriving(Clone, Show)]
 pub enum AutoAdjustment<'tcx> {
-    AdjustAddEnv(ty::TraitStore),
+    AdjustAddEnv(ast::DefId, ty::TraitStore),
+    AdjustReifyFnPointer(ast::DefId), // go from a fn-item type to a fn-pointer type
     AdjustDerefRef(AutoDerefRef<'tcx>)
 }
 
@@ -1243,11 +1244,17 @@ pub enum sty<'tcx> {
     ty_vec(Ty<'tcx>, Option<uint>), // Second field is length.
     ty_ptr(mt<'tcx>),
     ty_rptr(Region, mt<'tcx>),
-    ty_bare_fn(BareFnTy<'tcx>),
+
+    // If the def-id is Some(_), then this is the type of a specific
+    // fn item. Otherwise, if None(_), it a fn pointer type.
+    ty_bare_fn(Option<DefId>, BareFnTy<'tcx>),
+
     ty_closure(Box<ClosureTy<'tcx>>),
     ty_trait(Box<TyTrait<'tcx>>),
     ty_struct(DefId, Substs<'tcx>),
+
     ty_unboxed_closure(DefId, Region, Substs<'tcx>),
+
     ty_tup(Vec<Ty<'tcx>>),
 
     ty_param(ParamTy), // type parameter
@@ -2339,15 +2346,19 @@ pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, fty: ClosureTy<'tcx>) -> Ty<'tcx> {
     mk_t(cx, ty_closure(box fty))
 }
 
-pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>, fty: BareFnTy<'tcx>) -> Ty<'tcx> {
-    mk_t(cx, ty_bare_fn(fty))
+pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>,
+                        opt_def_id: Option<ast::DefId>,
+                        fty: BareFnTy<'tcx>) -> Ty<'tcx> {
+    mk_t(cx, ty_bare_fn(opt_def_id, fty))
 }
 
 pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
+                        def_id: ast::DefId,
                         input_tys: &[Ty<'tcx>],
                         output: Ty<'tcx>) -> Ty<'tcx> {
     let input_args = input_tys.iter().map(|ty| *ty).collect();
     mk_bare_fn(cx,
+               Some(def_id),
                BareFnTy {
                    unsafety: ast::Unsafety::Normal,
                    abi: abi::Rust,
@@ -3560,6 +3571,13 @@ pub fn type_is_bare_fn(ty: Ty) -> bool {
     }
 }
 
+pub fn type_is_bare_fn_item(ty: Ty) -> bool {
+    match ty.sty {
+        ty_bare_fn(Some(_), _) => true,
+        _ => false
+    }
+}
+
 pub fn type_is_fp(ty: Ty) -> bool {
     match ty.sty {
       ty_infer(FloatVar(_)) | ty_float(_) => true,
@@ -3975,9 +3993,9 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
     return match adjustment {
         Some(adjustment) => {
             match *adjustment {
-                AdjustAddEnv(store) => {
+                AdjustAddEnv(_, store) => {
                     match unadjusted_ty.sty {
-                        ty::ty_bare_fn(ref b) => {
+                        ty::ty_bare_fn(Some(_), ref b) => {
                             let bounds = ty::ExistentialBounds {
                                 region_bound: ReStatic,
                                 builtin_bounds: all_builtin_bounds(),
@@ -3994,7 +4012,21 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
                         }
                         ref b => {
                             cx.sess.bug(
-                                format!("add_env adjustment on non-bare-fn: \
+                                format!("add_env adjustment on non-fn-item: \
+                                         {}",
+                                        b).as_slice());
+                        }
+                    }
+                }
+
+                AdjustReifyFnPointer(_) => {
+                    match unadjusted_ty.sty {
+                        ty::ty_bare_fn(Some(_), ref b) => {
+                            ty::mk_bare_fn(cx, None, (*b).clone())
+                        }
+                        ref b => {
+                            cx.sess.bug(
+                                format!("AdjustReifyFnPointer adjustment on non-fn-item: \
                                          {}",
                                         b).as_slice());
                         }
@@ -4353,7 +4385,8 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
         ty_vec(_, None) => "slice".to_string(),
         ty_ptr(_) => "*-ptr".to_string(),
         ty_rptr(_, _) => "&-ptr".to_string(),
-        ty_bare_fn(_) => "extern fn".to_string(),
+        ty_bare_fn(Some(_), _) => format!("fn item"),
+        ty_bare_fn(None, _) => "fn pointer".to_string(),
         ty_closure(_) => "fn".to_string(),
         ty_trait(ref inner) => {
             format!("trait {}", item_path_str(cx, inner.principal.def_id()))
@@ -5884,8 +5917,9 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
                     region(state, r);
                     mt(state, m);
                 }
-                ty_bare_fn(ref b) => {
+                ty_bare_fn(opt_def_id, ref b) => {
                     byte!(14);
+                    hash!(opt_def_id);
                     hash!(b.unsafety);
                     hash!(b.abi);
                     fn_sig(state, &b.sig);
@@ -6252,6 +6286,7 @@ impl<'tcx> AutoAdjustment<'tcx> {
     pub fn is_identity(&self) -> bool {
         match *self {
             AdjustAddEnv(..) => false,
+            AdjustReifyFnPointer(..) => false,
             AdjustDerefRef(ref r) => r.is_identity(),
         }
     }
@@ -6367,8 +6402,11 @@ impl DebruijnIndex {
 impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
         match *self {
-            AdjustAddEnv(ref trait_store) => {
-                format!("AdjustAddEnv({})", trait_store)
+            AdjustAddEnv(def_id, ref trait_store) => {
+                format!("AdjustAddEnv({},{})", def_id.repr(tcx), trait_store)
+            }
+            AdjustReifyFnPointer(def_id) => {
+                format!("AdjustAddEnv({})", def_id.repr(tcx))
             }
             AdjustDerefRef(ref data) => {
                 data.repr(tcx)
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index d69ae96d07e..a35ea30b217 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -538,8 +538,8 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
         ty::ty_tup(ref ts) => {
             ty::ty_tup(ts.fold_with(this))
         }
-        ty::ty_bare_fn(ref f) => {
-            ty::ty_bare_fn(f.fold_with(this))
+        ty::ty_bare_fn(opt_def_id, ref f) => {
+            ty::ty_bare_fn(opt_def_id, f.fold_with(this))
         }
         ty::ty_closure(ref f) => {
             ty::ty_closure(box f.fold_with(this))
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index ca1e0d7de72..8b2c7f3a78a 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -542,6 +542,7 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         let class_ty = ty::lookup_item_type(tcx, parent_id).ty.subst(tcx, substs);
         let llty = type_of_dtor(ccx, class_ty);
         let dtor_ty = ty::mk_ctor_fn(ccx.tcx(),
+                                     did,
                                      &[glue::get_drop_glue_type(ccx, t)],
                                      ty::mk_nil(ccx.tcx()));
         get_extern_fn(ccx,
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index 1a753901f7e..7e7a6dfc48a 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -18,10 +18,9 @@ pub use self::AutorefArg::*;
 pub use self::CalleeData::*;
 pub use self::CallArgs::*;
 
-use arena::TypedArena;
-use back::{abi,link};
+use back::abi;
 use session;
-use llvm::{ValueRef, get_param};
+use llvm::{ValueRef};
 use llvm;
 use metadata::csearch;
 use middle::def;
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index d5d954f5a90..bbf8cb1c070 100644
--- a/src/librustc_trans/trans/closure.rs
+++ b/src/librustc_trans/trans/closure.rs
@@ -13,7 +13,6 @@ pub use self::ClosureKind::*;
 use back::abi;
 use back::link::mangle_internal_name_by_path_and_seq;
 use llvm::ValueRef;
-use middle::def;
 use middle::mem_categorization::Typer;
 use trans::adt;
 use trans::base::*;
@@ -603,21 +602,10 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
 
 pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                          closure_ty: Ty<'tcx>,
-                                         def: def::Def,
+                                         def_id: ast::DefId,
                                          fn_ptr: ValueRef,
-                                         is_local: bool) -> ValueRef {
-
-    let def_id = match def {
-        def::DefFn(did, _) | def::DefStaticMethod(did, _) |
-        def::DefVariant(_, did, _) | def::DefStruct(did) => did,
-        _ => {
-            ccx.sess().bug(format!("get_wrapper_for_bare_fn: \
-                                    expected a statically resolved fn, got \
-                                    {}",
-                                    def).as_slice());
-        }
-    };
-
+                                         is_local: bool) -> ValueRef
+{
     match ccx.closure_bare_wrapper_cache().borrow().get(&fn_ptr) {
         Some(&llval) => return llval,
         None => {}
@@ -697,11 +685,11 @@ pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 pub fn make_closure_from_bare_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                              closure_ty: Ty<'tcx>,
-                                             def: def::Def,
+                                             def_id: ast::DefId,
                                              fn_ptr: ValueRef)
                                              -> DatumBlock<'blk, 'tcx, Expr>  {
     let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust");
-    let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def, fn_ptr, true);
+    let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def_id, fn_ptr, true);
     fill_fn_pair(bcx, scratch.val, wrapper, C_null(Type::i8p(bcx.ccx())));
 
     DatumBlock::new(bcx, scratch.to_expr_datum())
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index e4f0543b5e7..1125a2aa529 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -190,16 +190,15 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr)
         None => { }
         Some(adj) => {
             match adj {
-                ty::AdjustAddEnv(ty::RegionTraitStore(ty::ReStatic, _)) => {
-                    let def = ty::resolve_expr(cx.tcx(), e);
+                ty::AdjustAddEnv(def_id, ty::RegionTraitStore(ty::ReStatic, _)) => {
                     let wrapper = closure::get_wrapper_for_bare_fn(cx,
                                                                    ety_adjusted,
-                                                                   def,
+                                                                   def_id,
                                                                    llconst,
                                                                    true);
                     llconst = C_struct(cx, &[wrapper, C_null(Type::i8p(cx))], false)
                 }
-                ty::AdjustAddEnv(store) => {
+                ty::AdjustAddEnv(_, store) => {
                     cx.sess()
                       .span_bug(e.span,
                                 format!("unexpected static function: {}",
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index 81892e5fa83..3e3252a347d 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -54,7 +54,7 @@ use trans::inline;
 use trans::tvec;
 use trans::type_of;
 use middle::ty::{struct_fields, tup_fields};
-use middle::ty::{AdjustDerefRef, AdjustAddEnv, AutoUnsafe};
+use middle::ty::{AdjustDerefRef, AdjustReifyFnPointer, AdjustAddEnv, AutoUnsafe};
 use middle::ty::{AutoPtr};
 use middle::ty::{mod, Ty};
 use middle::ty::MethodCall;
@@ -177,8 +177,9 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
            datum.to_string(bcx.ccx()),
            adjustment.repr(bcx.tcx()));
     match adjustment {
-        AdjustAddEnv(..) => {
-            datum = unpack_datum!(bcx, add_env(bcx, expr, datum));
+        AdjustAddEnv(def_id, _) => {
+            datum = unpack_datum!(bcx, add_env(bcx, def_id, expr, datum));
+        }
         }
         AdjustDerefRef(ref adj) => {
             let (autoderefs, use_autoref) = match adj.autoref {
@@ -466,6 +467,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 
     fn add_env<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                           def_id: ast::DefId,
                            expr: &ast::Expr,
                            datum: Datum<'tcx, Expr>)
                            -> DatumBlock<'blk, 'tcx, Expr> {
@@ -477,8 +479,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
         let closure_ty = expr_ty_adjusted(bcx, expr);
         let fn_ptr = datum.to_llscalarish(bcx);
-        let def = ty::resolve_expr(bcx.tcx(), expr);
-        closure::make_closure_from_bare_fn(bcx, closure_ty, def, fn_ptr)
+        closure::make_closure_from_bare_fn(bcx, closure_ty, def_id, fn_ptr)
     }
 }
 
diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs
index dea095ecaf5..e3c1e4b12bf 100644
--- a/src/librustc_trans/trans/glue.rs
+++ b/src/librustc_trans/trans/glue.rs
@@ -289,6 +289,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
 
         let dtor_ty = ty::mk_ctor_fn(bcx.tcx(),
+                                     class_did,
                                      &[get_drop_glue_type(bcx.ccx(), t)],
                                      ty::mk_nil(bcx.tcx()));
         let (_, variant_cx) = invoke(variant_cx, dtor_addr, args[], dtor_ty, None, false);
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index 15f6d7bc3f4..de7adda6bfd 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -639,7 +639,8 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                        m.repr(tcx),
                        substs.repr(tcx));
                 if m.generics.has_type_params(subst::FnSpace) ||
-                   ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) {
+                    ty::type_has_self(ty::mk_bare_fn(tcx, None, m.fty.clone()))
+                {
                     debug!("(making impl vtable) method has self or type \
                             params: {}",
                            token::get_name(name));
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 175763c874e..cd711deabed 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -954,7 +954,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                     tcx.sess.span_err(ast_ty.span,
                                       "variadic function must have C calling convention");
                 }
-                ty::mk_bare_fn(tcx, ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl))
+                ty::mk_bare_fn(tcx, None, ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl))
             }
             ast::TyClosure(ref f) => {
                 // Use corresponding trait store to figure out default bounds
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 2c220f29826..10801563f61 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -113,7 +113,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         self.add_obligations(&pick, &method_bounds_substs, &method_bounds);
 
         // Create the final `MethodCallee`.
-        let fty = ty::mk_bare_fn(self.tcx(), ty::BareFnTy {
+        let fty = ty::mk_bare_fn(self.tcx(), None, ty::BareFnTy {
             sig: ty::Binder(method_sig),
             unsafety: pick.method_ty.fty.unsafety,
             abi: pick.method_ty.fty.abi.clone(),
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 3b7eb22e56c..af5434e94fe 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -199,7 +199,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
                                                                        infer::FnCall,
                                                                        &fn_sig).0;
     let transformed_self_ty = fn_sig.inputs[0];
-    let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
+    let fty = ty::mk_bare_fn(tcx, None, ty::BareFnTy {
         sig: ty::Binder(fn_sig),
         unsafety: bare_fn_ty.unsafety,
         abi: bare_fn_ty.abi.clone(),
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index cd9a09efe08..7078f1e58c7 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1132,9 +1132,9 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 
     // Compute skolemized form of impl and trait method tys.
-    let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
+    let impl_fty = ty::mk_bare_fn(tcx, None, impl_m.fty.clone());
     let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
-    let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
+    let trait_fty = ty::mk_bare_fn(tcx, None, trait_m.fty.clone());
     let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
 
     // Check the impl method type IM is a subtype of the trait method
@@ -1389,6 +1389,8 @@ fn check_cast(fcx: &FnCtxt,
         }, t_e, None);
     }
 
+    let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
+
     let t_1_is_scalar = ty::type_is_scalar(t_1);
     let t_1_is_char = ty::type_is_char(t_1);
     let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
@@ -1396,7 +1398,9 @@ fn check_cast(fcx: &FnCtxt,
 
     // casts to scalars other than `char` and `bare fn` are trivial
     let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
-    if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
+    if t_e_is_bare_fn_item && t_1_is_bare_fn {
+        demand::coerce(fcx, e.span, t_1, &*e);
+    } else if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
         if t_1_is_float || ty::type_is_unsafe_ptr(t_1) {
             fcx.type_error_message(span, |actual| {
                 format!("illegal cast; cast through an \
@@ -1634,7 +1638,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                        span: Span,
                                        adj: &ty::AutoAdjustment<'tcx>) {
         match *adj {
-            ty::AdjustAddEnv(..) => { }
+            ty::AdjustAddEnv(..) |
+            ty::AdjustReifyFnPointer(..) => {
+            }
             ty::AdjustDerefRef(ref d_r) => {
                 match d_r.autoref {
                     Some(ref a_r) => {
@@ -5627,7 +5633,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
         };
         (n_tps, inputs, ty::FnConverging(output))
     };
-    let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
+    let fty = ty::mk_bare_fn(tcx, None, ty::BareFnTy {
         unsafety: ast::Unsafety::Unsafe,
         abi: abi::RustIntrinsic,
         sig: ty::Binder(FnSig {
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 700d1211606..b123d97d897 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -15,7 +15,6 @@ use self::ResolveReason::*;
 
 use astconv::AstConv;
 use check::FnCtxt;
-use middle::def;
 use middle::pat_util;
 use middle::ty::{mod, Ty, MethodCall, MethodCallee};
 use middle::ty_fold::{TypeFolder,TypeFoldable};
@@ -267,25 +266,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             Some(adjustment) => {
                 let adj_object = ty::adjust_is_object(&adjustment);
                 let resolved_adjustment = match adjustment {
-                    ty::AdjustAddEnv(store) => {
-                        // FIXME(eddyb) #2190 Allow only statically resolved
-                        // bare functions to coerce to a closure to avoid
-                        // constructing (slower) indirect call wrappers.
-                        match self.tcx().def_map.borrow().get(&id) {
-                            Some(&def::DefFn(..)) |
-                            Some(&def::DefStaticMethod(..)) |
-                            Some(&def::DefVariant(..)) |
-                            Some(&def::DefStruct(_)) => {
-                            }
-                            _ => {
-                                span_err!(self.tcx().sess, reason.span(self.tcx()), E0100,
-                                    "cannot coerce non-statically resolved bare fn to closure");
-                                span_help!(self.tcx().sess, reason.span(self.tcx()),
-                                    "consider embedding the function in a closure");
-                            }
-                        }
+                    ty::AdjustAddEnv(def_id, store) => {
+                        ty::AdjustAddEnv(def_id, self.resolve(&store, reason))
+                    }
 
-                        ty::AdjustAddEnv(self.resolve(&store, reason))
+                    ty::AdjustReifyFnPointer(def_id) => {
+                        ty::AdjustReifyFnPointer(def_id)
                     }
 
                     ty::AdjustDerefRef(adj) => {
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 5d0bb6622c2..bba6af95845 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -235,7 +235,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             // impl, plus its own.
             let new_polytype = ty::Polytype {
                 generics: new_method_ty.generics.clone(),
-                ty: ty::mk_bare_fn(tcx, new_method_ty.fty.clone())
+                ty: ty::mk_bare_fn(tcx, Some(new_did), new_method_ty.fty.clone())
             };
             debug!("new_polytype={}", new_polytype.repr(tcx));
 
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 3f59b50337f..af996da5543 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -211,13 +211,15 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     // Create a set of parameter types shared among all the variants.
     for variant in variants.iter() {
+        let variant_def_id = local_def(variant.node.id);
+
         // Nullary enum constructors get turned into constants; n-ary enum
         // constructors get turned into functions.
         let result_ty = match variant.node.kind {
             ast::TupleVariantKind(ref args) if args.len() > 0 => {
                 let rs = ExplicitRscope;
                 let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
-                ty::mk_ctor_fn(tcx, input_tys.as_slice(), enum_ty)
+                ty::mk_ctor_fn(tcx, variant_def_id, input_tys.as_slice(), enum_ty)
             }
 
             ast::TupleVariantKind(_) => {
@@ -246,7 +248,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             ty: result_ty
         };
 
-        tcx.tcache.borrow_mut().insert(local_def(variant.node.id), pty);
+        tcx.tcache.borrow_mut().insert(variant_def_id, pty);
 
         write_ty_to_tcx(tcx, variant.node.id, result_ty);
     }
@@ -353,7 +355,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             m.def_id,
             Polytype {
                 generics: m.generics.clone(),
-                ty: ty::mk_bare_fn(ccx.tcx, m.fty.clone()) });
+                ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), m.fty.clone()) });
     }
 
     fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
@@ -519,6 +521,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
             tcx.sess.span_err(m.span, "duplicate method in trait impl");
         }
 
+        let m_def_id = local_def(m.id);
         let mty = Rc::new(ty_of_method(ccx,
                                        convert_method_context,
                                        container,
@@ -526,13 +529,13 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
                                        untransformed_rcvr_ty,
                                        rcvr_ty_generics,
                                        rcvr_visibility));
-        let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
+        let fty = ty::mk_bare_fn(tcx, Some(m_def_id), mty.fty.clone());
         debug!("method {} (id {}) has type {}",
                 m.pe_ident().repr(tcx),
                 m.id,
                 fty.repr(tcx));
         tcx.tcache.borrow_mut().insert(
-            local_def(m.id),
+            m_def_id,
             Polytype {
                 generics: mty.generics.clone(),
                 ty: fty
@@ -1279,6 +1282,7 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         |field| (*tcx.tcache.borrow())[
                             local_def(field.node.id)].ty).collect();
                 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
+                                                local_def(ctor_id),
                                                 inputs.as_slice(),
                                                 selfty);
                 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
@@ -1461,7 +1465,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
             };
             let pty = Polytype {
                 generics: ty_generics,
-                ty: ty::mk_bare_fn(ccx.tcx, tofd)
+                ty: ty::mk_bare_fn(ccx.tcx, Some(local_def(it.id)), tofd)
             };
             debug!("type of {} (id {}) is {}",
                     token::get_ident(it.ident),
@@ -2138,6 +2142,7 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     let t_fn = ty::mk_bare_fn(
         ccx.tcx,
+        None,
         ty::BareFnTy {
             abi: abi,
             unsafety: ast::Unsafety::Unsafe,
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 49c5f13fa73..c30293e4765 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -102,6 +102,7 @@ use util::ppaux;
 use syntax::codemap::Span;
 use syntax::print::pprust::*;
 use syntax::{ast, ast_map, abi};
+use syntax::ast_util::local_def;
 
 #[cfg(stage0)]
 mod diagnostics;
@@ -224,7 +225,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 }
                 _ => ()
             }
-            let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy {
+            let se_ty = ty::mk_bare_fn(tcx, Some(local_def(main_id)), ty::BareFnTy {
                 unsafety: ast::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
@@ -272,7 +273,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 _ => ()
             }
 
-            let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy {
+            let se_ty = ty::mk_bare_fn(tcx, Some(local_def(start_id)), ty::BareFnTy {
                 unsafety: ast::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {