about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_trans/trans/_match.rs11
-rw-r--r--src/librustc_trans/trans/base.rs54
-rw-r--r--src/librustc_trans/trans/callee.rs179
-rw-r--r--src/librustc_trans/trans/common.rs11
-rw-r--r--src/librustc_trans/trans/consts.rs4
-rw-r--r--src/librustc_trans/trans/controlflow.rs21
-rw-r--r--src/librustc_trans/trans/expr.rs4
-rw-r--r--src/librustc_trans/trans/glue.rs20
-rw-r--r--src/librustc_trans/trans/inline.rs79
-rw-r--r--src/librustc_trans/trans/intrinsic.rs19
-rw-r--r--src/librustc_trans/trans/meth.rs14
-rw-r--r--src/librustc_trans/trans/mir/block.rs2
-rw-r--r--src/librustc_trans/trans/mir/rvalue.rs5
13 files changed, 197 insertions, 226 deletions
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index e277a535028..8aea2f1ec4f 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -200,12 +200,13 @@ use middle::lang_items::StrEqFnLangItem;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::Categorization;
 use middle::pat_util::*;
+use middle::subst::Substs;
 use trans::adt;
 use trans::base::*;
 use trans::build::{AddCase, And, Br, CondBr, GEPi, InBoundsGEP, Load, PointerCast};
 use trans::build::{Not, Store, Sub, add_comment};
 use trans::build;
-use trans::callee;
+use trans::callee::{Callee, ArgVals};
 use trans::cleanup::{self, CleanupMethods, DropHintMethods};
 use trans::common::*;
 use trans::consts;
@@ -881,7 +882,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                               rhs_t: Ty<'tcx>,
                               debug_loc: DebugLoc)
                               -> Result<'blk, 'tcx> {
-    fn compare_str<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
+    fn compare_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                lhs_data: ValueRef,
                                lhs_len: ValueRef,
                                rhs_data: ValueRef,
@@ -889,11 +890,13 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                                rhs_t: Ty<'tcx>,
                                debug_loc: DebugLoc)
                                -> Result<'blk, 'tcx> {
-        let did = langcall(cx,
+        let did = langcall(bcx,
                            None,
                            &format!("comparison of `{}`", rhs_t),
                            StrEqFnLangItem);
-        callee::trans_lang_call(cx, did, &[lhs_data, lhs_len, rhs_data, rhs_len], None, debug_loc)
+        let args = [lhs_data, lhs_len, rhs_data, rhs_len];
+        Callee::def(bcx.ccx(), did, bcx.tcx().mk_substs(Substs::empty()))
+            .call(bcx, debug_loc, ArgVals(&args), None)
     }
 
     let _icx = push_ctxt("compare_values");
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 03f3671a6b1..b2d7b83887e 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -57,7 +57,7 @@ use trans::assert_dep_graph;
 use trans::attributes;
 use trans::build::*;
 use trans::builder::{Builder, noname};
-use trans::callee;
+use trans::callee::{Callee, CallArgs, ArgExprs, ArgVals};
 use trans::cleanup::{self, CleanupMethods, DropHint};
 use trans::closure;
 use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_uint, C_integral};
@@ -280,11 +280,9 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("malloc_raw_exchange");
 
     // Allocate space:
-    let r = callee::trans_lang_call(bcx,
-                                    require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem),
-                                    &[size, align],
-                                    None,
-                                    debug_loc);
+    let def_id = require_alloc_fn(bcx, info_ty, ExchangeMallocFnLangItem);
+    let r = Callee::def(bcx.ccx(), def_id, bcx.tcx().mk_substs(Substs::empty()))
+        .call(bcx, debug_loc, ArgVals(&[size, align]), None);
 
     Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
 }
@@ -1219,9 +1217,8 @@ pub fn trans_unwind_resume(bcx: Block, lpval: ValueRef) {
         Resume(bcx, lpval);
     } else {
         let exc_ptr = ExtractValue(bcx, lpval, 0);
-        let llunwresume = bcx.fcx.eh_unwind_resume();
-        Call(bcx, llunwresume, &[exc_ptr], None, DebugLoc::None);
-        Unreachable(bcx);
+        bcx.fcx.eh_unwind_resume()
+            .call(bcx, DebugLoc::None, ArgVals(&[exc_ptr]), None);
     }
 }
 
@@ -2147,20 +2144,10 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                   closure::ClosureEnv::NotClosure);
 }
 
-pub fn trans_enum_variant<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                    ctor_id: ast::NodeId,
-                                    disr: Disr,
-                                    param_substs: &'tcx Substs<'tcx>,
-                                    llfndecl: ValueRef) {
-    let _icx = push_ctxt("trans_enum_variant");
-
-    trans_enum_variant_or_tuple_like_struct(ccx, ctor_id, disr, param_substs, llfndecl);
-}
-
 pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                                  ctor_ty: Ty<'tcx>,
                                                  disr: Disr,
-                                                 args: callee::CallArgs,
+                                                 args: CallArgs,
                                                  dest: expr::Dest,
                                                  debug_loc: DebugLoc)
                                                  -> Result<'blk, 'tcx> {
@@ -2188,7 +2175,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
     if !type_is_zero_size(ccx, result_ty) {
         match args {
-            callee::ArgExprs(exprs) => {
+            ArgExprs(exprs) => {
                 let fields = exprs.iter().map(|x| &**x).enumerate().collect::<Vec<_>>();
                 bcx = expr::trans_adt(bcx,
                                       result_ty,
@@ -2204,7 +2191,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         // Just eval all the expressions (if any). Since expressions in Rust can have arbitrary
         // contents, there could be side-effects we need from them.
         match args {
-            callee::ArgExprs(exprs) => {
+            ArgExprs(exprs) => {
                 for expr in exprs {
                     bcx = expr::trans_into(bcx, expr, expr::Ignore);
                 }
@@ -2500,8 +2487,9 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
                 // compilation unit that references the item, so it will still get
                 // translated everywhere it's needed.
                 for (ref ccx, is_origin) in ccx.maybe_iter(!from_external && trans_everywhere) {
-                    let llfn = get_item_val(ccx, item.id);
-                    let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
+                    let empty_substs = tcx.mk_substs(Substs::trans_empty());
+                    let def_id = tcx.map.local_def_id(item.id);
+                    let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
                     if abi != Abi::Rust {
                         foreign::trans_rust_fn_with_foreign_abi(ccx,
                                                                 &decl,
@@ -2536,9 +2524,8 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
                         // error in trans. This is used to write compile-fail tests
                         // that actually test that compilation succeeds without
                         // reporting an error.
-                        let item_def_id = ccx.tcx().map.local_def_id(item.id);
-                        if ccx.tcx().has_attr(item_def_id, "rustc_error") {
-                            ccx.tcx().sess.span_fatal(item.span, "compilation successful");
+                        if tcx.has_attr(def_id, "rustc_error") {
+                            tcx.sess.span_fatal(item.span, "compilation successful");
                         }
                     }
                 }
@@ -2671,17 +2658,10 @@ pub fn create_entry_wrapper(ccx: &CrateContext, sp: Span, main_llfn: ValueRef) {
             let (start_fn, args) = if use_start_lang_item {
                 let start_def_id = match ccx.tcx().lang_items.require(StartFnLangItem) {
                     Ok(id) => id,
-                    Err(s) => {
-                        ccx.sess().fatal(&s[..]);
-                    }
-                };
-                let start_fn = if let Some(start_node_id) = ccx.tcx()
-                                                               .map
-                                                               .as_local_node_id(start_def_id) {
-                    get_item_val(ccx, start_node_id)
-                } else {
-                    get_extern_fn(ccx, start_def_id).val
+                    Err(s) => ccx.sess().fatal(&s)
                 };
+                let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
+                let start_fn = Callee::def(ccx, start_def_id, empty_substs).reify(ccx).val;
                 let args = {
                     let opaque_rust_main =
                         llvm::LLVMBuildPointerCast(bld,
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index 7e0e01c3150..318c968692c 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -97,26 +97,19 @@ impl<'tcx> Callee<'tcx> {
     pub fn method<'blk>(bcx: Block<'blk, 'tcx>,
                         method: ty::MethodCallee<'tcx>) -> Callee<'tcx> {
         let substs = bcx.tcx().mk_substs(bcx.fcx.monomorphize(&method.substs));
-        let ty = bcx.fcx.monomorphize(&method.ty);
-        Callee::def(bcx.ccx(), method.def_id, substs, ty)
+        Callee::def(bcx.ccx(), method.def_id, substs)
     }
 
     /// Function or method definition.
     pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>,
                    def_id: DefId,
-                   substs: &'tcx subst::Substs<'tcx>,
-                   ty: Ty<'tcx>)
+                   substs: &'tcx subst::Substs<'tcx>)
                    -> Callee<'tcx> {
         let tcx = ccx.tcx();
 
         if substs.self_ty().is_some() {
             // Only trait methods can have a Self parameter.
-            let method_item = tcx.impl_or_trait_item(def_id);
-            let trait_id = method_item.container().id();
-            let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id));
-            let vtbl = common::fulfill_obligation(ccx, DUMMY_SP, trait_ref);
-            return meth::callee_for_trait_impl(ccx, def_id, substs,
-                                               trait_id, ty, vtbl);
+            return Callee::trait_method(ccx, def_id, substs);
         }
 
         let maybe_node_id = inline::get_local_instance(ccx, def_id)
@@ -124,34 +117,95 @@ impl<'tcx> Callee<'tcx> {
         let maybe_ast_node = maybe_node_id.and_then(|node_id| {
             tcx.map.find(node_id)
         });
-        match maybe_ast_node {
+
+        let data = match maybe_ast_node {
             Some(hir_map::NodeStructCtor(_)) => {
-                return Callee {
-                    data: NamedTupleConstructor(Disr(0)),
-                    ty: ty
-                };
+                NamedTupleConstructor(Disr(0))
             }
             Some(hir_map::NodeVariant(_)) => {
                 let vinfo = common::inlined_variant_def(ccx, maybe_node_id.unwrap());
-                assert_eq!(vinfo.kind(), ty::VariantKind::Tuple);
+                NamedTupleConstructor(Disr::from(vinfo.disr_val))
+            }
+            Some(hir_map::NodeForeignItem(fi)) if {
+                let abi = tcx.map.get_foreign_abi(fi.id);
+                abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic
+            } => Intrinsic,
+
+            _ => return Callee::ptr(get_fn(ccx, def_id, substs))
+        };
+
+        Callee {
+            data: data,
+            ty: def_ty(tcx, def_id, substs)
+        }
+    }
+
+    /// Trait method, which has to be resolved to an impl method.
+    pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>,
+                            def_id: DefId,
+                            substs: &'tcx subst::Substs<'tcx>)
+                            -> Callee<'tcx> {
+        let tcx = ccx.tcx();
 
-                return Callee {
-                    data: NamedTupleConstructor(Disr::from(vinfo.disr_val)),
-                    ty: ty
+        let method_item = tcx.impl_or_trait_item(def_id);
+        let trait_id = method_item.container().id();
+        let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id));
+        match common::fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
+            traits::VtableImpl(vtable_impl) => {
+                let impl_did = vtable_impl.impl_def_id;
+                let mname = tcx.item_name(def_id);
+                // create a concatenated set of substitutions which includes
+                // those from the impl and those from the method:
+                let impl_substs = vtable_impl.substs.with_method_from(&substs);
+                let substs = tcx.mk_substs(impl_substs);
+                let mth = tcx.get_impl_method(impl_did, substs, mname);
+
+                // Translate the function, bypassing Callee::def.
+                // That is because default methods have the same ID as the
+                // trait method used to look up the impl method that ended
+                // up here, so calling Callee::def would infinitely recurse.
+                Callee::ptr(get_fn(ccx, mth.method.def_id, mth.substs))
+            }
+            traits::VtableClosure(vtable_closure) => {
+                // The substitutions should have no type parameters remaining
+                // after passing through fulfill_obligation
+                let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
+                let llfn = closure::trans_closure_method(ccx,
+                                                         vtable_closure.closure_def_id,
+                                                         vtable_closure.substs,
+                                                         trait_closure_kind);
+
+                let method_ty = def_ty(tcx, def_id, substs);
+                let fn_ptr_ty = match method_ty.sty {
+                    ty::TyFnDef(_, _, fty) => tcx.mk_ty(ty::TyFnPtr(fty)),
+                    _ => unreachable!("expected fn item type, found {}",
+                                      method_ty)
                 };
+                Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty))
             }
-            Some(hir_map::NodeForeignItem(fi)) => {
-                let abi = tcx.map.get_foreign_abi(fi.id);
-                if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
-                    return Callee {
-                        data: Intrinsic(fi.id, substs),
-                        ty: ty
-                    };
+            traits::VtableFnPointer(fn_ty) => {
+                let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
+                let llfn = trans_fn_pointer_shim(ccx, trait_closure_kind, fn_ty);
+
+                let method_ty = def_ty(tcx, def_id, substs);
+                let fn_ptr_ty = match method_ty.sty {
+                    ty::TyFnDef(_, _, fty) => tcx.mk_ty(ty::TyFnPtr(fty)),
+                    _ => unreachable!("expected fn item type, found {}",
+                                      method_ty)
+                };
+                Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty))
+            }
+            traits::VtableObject(ref data) => {
+                Callee {
+                    data: Virtual(traits::get_vtable_index_of_object_method(
+                        tcx, data, def_id)),
+                    ty: def_ty(tcx, def_id, substs)
                 }
             }
-            _ => {}
+            vtable => {
+                unreachable!("resolved vtable bad vtable {:?} in trans", vtable);
+            }
         }
-        Callee::ptr(trans_fn_ref_with_substs(ccx, def_id, Some(ty), substs))
     }
 
     /// This behemoth of a function translates function calls. Unfortunately, in
@@ -187,7 +241,7 @@ impl<'tcx> Callee<'tcx> {
             Virtual(idx) => meth::trans_object_shim(ccx, self.ty, idx),
             NamedTupleConstructor(_) => match self.ty.sty {
                 ty::TyFnDef(def_id, substs, _) => {
-                    return trans_fn_ref_with_substs(ccx, def_id, Some(self.ty), substs);
+                    return get_fn(ccx, def_id, substs);
                 }
                 _ => unreachable!("expected fn item type, found {}", self.ty)
             },
@@ -196,31 +250,13 @@ impl<'tcx> Callee<'tcx> {
     }
 }
 
-/// Translates a reference (with id `ref_id`) to the fn/method with id `def_id` into a function
-/// pointer. This may require monomorphization or inlining.
-pub fn trans_fn_ref<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                              def_id: DefId,
-                              node: ExprOrMethodCall,
-                              param_substs: &'tcx subst::Substs<'tcx>)
-                              -> Datum<'tcx, Rvalue> {
-    let _icx = push_ctxt("trans_fn_ref");
-
-    let substs = common::node_id_substs(ccx, node, param_substs);
-    debug!("trans_fn_ref(def_id={:?}, node={:?}, substs={:?})",
-           def_id,
-           node,
-           substs);
-    let ref_ty = match node {
-        ExprId(0) => return trans_fn_ref_with_substs(ccx, def_id, None, substs),
-        ExprId(id) => ccx.tcx().node_id_to_type(id),
-        MethodCallKey(method_call) => {
-            ccx.tcx().tables.borrow().method_map[&method_call].ty
-        }
-    };
-    let ref_ty = monomorphize::apply_param_substs(ccx.tcx(),
-                                                  param_substs,
-                                                  &ref_ty);
-    trans_fn_ref_with_substs(ccx, def_id, Some(ref_ty), substs)
+/// Given a DefId and some Substs, produces the monomorphic item type.
+fn def_ty<'tcx>(tcx: &TyCtxt<'tcx>,
+                def_id: DefId,
+                substs: &'tcx subst::Substs<'tcx>)
+                -> Ty<'tcx> {
+    let ty = tcx.lookup_item_type(def_id).ty;
+    monomorphize::apply_param_substs(tcx, substs, &ty)
 }
 
 /// Translates an adapter that implements the `Fn` trait for a fn
@@ -323,7 +359,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
     let llfnpointer = match bare_fn_ty.sty {
         ty::TyFnDef(def_id, substs, _) => {
             // Function definitions have to be turned into a pointer.
-            Callee::def(ccx, def_id, substs, bare_fn_ty).reify(ccx).val
+            Callee::def(ccx, def_id, substs).reify(ccx).val
         }
 
         // the first argument (`self`) will be ptr to the fn pointer
@@ -360,25 +396,14 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
 ///
 /// - `ccx`: the crate context
 /// - `def_id`: def id of the fn or method item being referenced
-/// - `node`: node id of the reference to the fn/method, if applicable.
-///   This parameter may be zero; but, if so, the resulting value may not
-///   have the right type, so it must be cast before being used.
-/// - `ref_ty`: monotype of the reference to the fn/method, if applicable.
-///   This parameter may be None; but, if so, the resulting value may not
-///   have the right type, so it must be cast before being used.
 /// - `substs`: values for each of the fn/method's parameters
-pub fn trans_fn_ref_with_substs<'a, 'tcx>(
-    ccx: &CrateContext<'a, 'tcx>,
-    def_id: DefId,
-    ref_ty: Option<Ty<'tcx>>,
-    substs: &'tcx subst::Substs<'tcx>)
-    -> Datum<'tcx, Rvalue>
-{
-    let _icx = push_ctxt("trans_fn_ref_with_substs");
+fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                    def_id: DefId,
+                    substs: &'tcx subst::Substs<'tcx>)
+                    -> Datum<'tcx, Rvalue> {
     let tcx = ccx.tcx();
 
-    debug!("trans_fn_ref_with_substs(def_id={:?}, ref_ty={:?}, substs={:?})",
-           def_id, ref_ty, substs);
+    debug!("get_fn(def_id={:?}, substs={:?})", def_id, substs);
 
     assert!(!substs.types.needs_infer());
     assert!(!substs.types.has_escaping_regions());
@@ -408,7 +433,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
     let must_monomorphise =
         !substs.types.is_empty() || is_named_tuple_constructor(tcx, def_id);
 
-    debug!("trans_fn_ref_with_substs({:?}) must_monomorphise: {}",
+    debug!("get_fn({:?}) must_monomorphise: {}",
            def_id, must_monomorphise);
 
     // Create a monomorphic version of generic functions
@@ -494,16 +519,6 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
 // ______________________________________________________________________
 // Translating calls
 
-pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                   did: DefId,
-                                   args: &[ValueRef],
-                                   dest: Option<expr::Dest>,
-                                   debug_loc: DebugLoc)
-                                   -> Result<'blk, 'tcx> {
-    let datum = trans_fn_ref(bcx.ccx(), did, ExprId(0), bcx.fcx.param_substs);
-    Callee::ptr(datum).call(bcx, debug_loc, ArgVals(args), dest)
-}
-
 fn trans_call_inner<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                     debug_loc: DebugLoc,
                                     callee: Callee<'tcx>,
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index ec24242a010..c974173f765 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -512,11 +512,12 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
         // `rust_eh_personality` function, but rather we wired it up to the
         // CRT's custom personality function, which forces LLVM to consider
         // landing pads as "landing pads for SEH".
-        let target = &self.ccx.sess().target.target;
-        match self.ccx.tcx().lang_items.eh_personality() {
-            Some(def_id) if !base::wants_msvc_seh(self.ccx.sess()) => {
-                callee::trans_fn_ref(self.ccx, def_id, ExprId(0),
-                                     self.param_substs).val
+        let ccx = self.ccx;
+        let tcx = ccx.tcx();
+        let target = &ccx.sess().target.target;
+        match tcx.lang_items.eh_personality() {
+            Some(def_id) if !base::wants_msvc_seh(ccx.sess()) => {
+                Callee::def(ccx, def_id, tcx.mk_substs(Substs::empty())).reify(ccx).val
             }
             _ => {
                 let mut personality = self.ccx.eh_personality().borrow_mut();
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index 66fdc2056a3..ec550c680de 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -352,9 +352,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         Some(AdjustReifyFnPointer) => {
             match ety.sty {
                 ty::TyFnDef(def_id, substs, _) => {
-                    let datum = Callee::def(cx, def_id, substs, ety).reify(cx);
-                    llconst = datum.val;
-                    ety_adjusted = datum.ty;
+                    llconst = Callee::def(cx, def_id, substs).reify(cx).val;
                 }
                 _ => {
                     unreachable!("{} cannot be reified to a fn ptr", ety)
diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs
index 805c1388627..ef8d4cfff9d 100644
--- a/src/librustc_trans/trans/controlflow.rs
+++ b/src/librustc_trans/trans/controlflow.rs
@@ -11,10 +11,11 @@
 use llvm::ValueRef;
 use middle::def::Def;
 use middle::lang_items::{PanicFnLangItem, PanicBoundsCheckFnLangItem};
+use middle::subst::Substs;
 use trans::base::*;
 use trans::basic_block::BasicBlock;
 use trans::build::*;
-use trans::callee;
+use trans::callee::{Callee, ArgVals};
 use trans::cleanup::CleanupMethods;
 use trans::cleanup;
 use trans::common::*;
@@ -405,13 +406,8 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let expr_file_line = consts::addr_of(ccx, expr_file_line_const, align, "panic_loc");
     let args = vec!(expr_file_line);
     let did = langcall(bcx, Some(call_info.span), "", PanicFnLangItem);
-    let bcx = callee::trans_lang_call(bcx,
-                                      did,
-                                      &args[..],
-                                      Some(expr::Ignore),
-                                      call_info.debug_loc()).bcx;
-    Unreachable(bcx);
-    return bcx;
+    Callee::def(ccx, did, ccx.tcx().mk_substs(Substs::empty()))
+        .call(bcx, call_info.debug_loc(), ArgVals(&args), None).bcx
 }
 
 pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@@ -438,11 +434,6 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let file_line = consts::addr_of(ccx, file_line_const, align, "panic_bounds_check_loc");
     let args = vec!(file_line, index, len);
     let did = langcall(bcx, Some(call_info.span), "", PanicBoundsCheckFnLangItem);
-    let bcx = callee::trans_lang_call(bcx,
-                                      did,
-                                      &args[..],
-                                      Some(expr::Ignore),
-                                      call_info.debug_loc()).bcx;
-    Unreachable(bcx);
-    return bcx;
+    Callee::def(ccx, did, ccx.tcx().mk_substs(Substs::empty()))
+        .call(bcx, call_info.debug_loc(), ArgVals(&args), None).bcx
 }
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index beae363f968..63612cd1e1f 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -385,7 +385,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         AdjustReifyFnPointer => {
             match datum.ty.sty {
                 ty::TyFnDef(def_id, substs, _) => {
-                    datum = Callee::def(bcx.ccx(), def_id, substs, datum.ty)
+                    datum = Callee::def(bcx.ccx(), def_id, substs)
                         .reify(bcx.ccx()).to_expr_datum();
                 }
                 _ => {
@@ -1143,7 +1143,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 let f = unpack_datum!(bcx, trans(bcx, f));
                 (match f.ty.sty {
                     ty::TyFnDef(def_id, substs, _) => {
-                        Callee::def(bcx.ccx(), def_id, substs, f.ty)
+                        Callee::def(bcx.ccx(), def_id, substs)
                     }
                     ty::TyFnPtr(_) => {
                         let f = unpack_datum!(bcx,
diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs
index b899dbe47ca..c93548fe1c2 100644
--- a/src/librustc_trans/trans/glue.rs
+++ b/src/librustc_trans/trans/glue.rs
@@ -25,7 +25,7 @@ use trans::adt;
 use trans::adt::GetDtorType; // for tcx.dtor_type()
 use trans::base::*;
 use trans::build::*;
-use trans::callee;
+use trans::callee::{Callee, ArgVals};
 use trans::cleanup;
 use trans::cleanup::CleanupMethods;
 use trans::collector::{self, TransItem};
@@ -44,19 +44,18 @@ use libc::c_uint;
 use syntax::ast;
 use syntax::codemap::DUMMY_SP;
 
-pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
+pub fn trans_exchange_free_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                            v: ValueRef,
                                            size: ValueRef,
                                            align: ValueRef,
                                            debug_loc: DebugLoc)
                                            -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_exchange_free");
-    let ccx = cx.ccx();
-    callee::trans_lang_call(cx,
-        langcall(cx, None, "", ExchangeFreeFnLangItem),
-        &[PointerCast(cx, v, Type::i8p(ccx)), size, align],
-        Some(expr::Ignore),
-        debug_loc).bcx
+
+    let def_id = langcall(bcx, None, "", ExchangeFreeFnLangItem);
+    let args = [PointerCast(bcx, v, Type::i8p(bcx.ccx())), size, align];
+    Callee::def(bcx.ccx(), def_id, bcx.tcx().mk_substs(Substs::empty()))
+        .call(bcx, debug_loc, ArgVals(&args), None).bcx
 }
 
 pub fn trans_exchange_free<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
@@ -366,9 +365,8 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         _ => tcx.sess.bug(&format!("dtor for {:?} is not an impl???", t))
     };
     let dtor_did = def.destructor().unwrap();
-    bcx = callee::Callee::ptr(callee::trans_fn_ref_with_substs(
-            bcx.ccx(), dtor_did, None, vtbl.substs))
-        .call(bcx, DebugLoc::None, callee::ArgVals(args), Some(expr::Ignore)).bcx;
+    bcx = Callee::def(bcx.ccx(), dtor_did, vtbl.substs)
+        .call(bcx, DebugLoc::None, ArgVals(args), None).bcx;
 
     bcx.fcx.pop_and_trans_custom_cleanup_scope(bcx, contents_scope)
 }
diff --git a/src/librustc_trans/trans/inline.rs b/src/librustc_trans/trans/inline.rs
index 0dcb0c29faf..c260f77e887 100644
--- a/src/librustc_trans/trans/inline.rs
+++ b/src/librustc_trans/trans/inline.rs
@@ -12,7 +12,8 @@ use llvm::{AvailableExternallyLinkage, InternalLinkage, SetLinkage};
 use middle::cstore::{CrateStore, FoundAst, InlinedItem};
 use middle::def_id::DefId;
 use middle::subst::Substs;
-use trans::base::{push_ctxt, trans_item, get_item_val, trans_fn};
+use trans::base::{push_ctxt, trans_item, trans_fn};
+use trans::callee::Callee;
 use trans::common::*;
 
 use rustc::dep_graph::DepNode;
@@ -21,14 +22,15 @@ use rustc_front::hir;
 fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
     debug!("instantiate_inline({:?})", fn_id);
     let _icx = push_ctxt("instantiate_inline");
-    let _task = ccx.tcx().dep_graph.in_task(DepNode::TransInlinedItem(fn_id));
+    let tcx = ccx.tcx();
+    let _task = tcx.dep_graph.in_task(DepNode::TransInlinedItem(fn_id));
 
     match ccx.external().borrow().get(&fn_id) {
         Some(&Some(node_id)) => {
             // Already inline
             debug!("instantiate_inline({}): already inline as node id {}",
-                   ccx.tcx().item_path_str(fn_id), node_id);
-            let node_def_id = ccx.tcx().map.local_def_id(node_id);
+                   tcx.item_path_str(fn_id), node_id);
+            let node_def_id = tcx.map.local_def_id(node_id);
             return Some(node_def_id);
         }
         Some(&None) => {
@@ -39,7 +41,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
         }
     }
 
-    let inlined = ccx.tcx().sess.cstore.maybe_get_item_ast(ccx.tcx(), fn_id);
+    let inlined = tcx.sess.cstore.maybe_get_item_ast(tcx, fn_id);
     let inline_id = match inlined {
         FoundAst::NotFound => {
             ccx.external().borrow_mut().insert(fn_id, None);
@@ -52,38 +54,27 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
             ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
             trans_item(ccx, item);
 
-            let linkage = match item.node {
-                hir::ItemFn(_, _, _, _, ref generics, _) => {
-                    if generics.is_type_parameterized() {
-                        // Generics have no symbol, so they can't be given any
-                        // linkage.
-                        None
+            if let hir::ItemFn(_, _, _, _, ref generics, _) = item.node {
+                // Generics have no symbol, so they can't be given any linkage.
+                if !generics.is_type_parameterized() {
+                    let linkage = if ccx.sess().opts.cg.codegen_units == 1 {
+                        // We could use AvailableExternallyLinkage here,
+                        // but InternalLinkage allows LLVM to optimize more
+                        // aggressively (at the cost of sometimes
+                        // duplicating code).
+                        InternalLinkage
                     } else {
-                        if ccx.sess().opts.cg.codegen_units == 1 {
-                            // We could use AvailableExternallyLinkage here,
-                            // but InternalLinkage allows LLVM to optimize more
-                            // aggressively (at the cost of sometimes
-                            // duplicating code).
-                            Some(InternalLinkage)
-                        } else {
-                            // With multiple compilation units, duplicated code
-                            // is more of a problem.  Also, `codegen_units > 1`
-                            // means the user is okay with losing some
-                            // performance.
-                            Some(AvailableExternallyLinkage)
-                        }
-                    }
-                }
-                hir::ItemConst(..) => None,
-                _ => unreachable!(),
-            };
-
-            match linkage {
-                Some(linkage) => {
-                    let g = get_item_val(ccx, item.id);
-                    SetLinkage(g, linkage);
+                        // With multiple compilation units, duplicated code
+                        // is more of a problem.  Also, `codegen_units > 1`
+                        // means the user is okay with losing some
+                        // performance.
+                        AvailableExternallyLinkage
+                    };
+                    let empty_substs = tcx.mk_substs(Substs::trans_empty());
+                    let def_id = tcx.map.local_def_id(item.id);
+                    let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
+                    SetLinkage(llfn, linkage);
                 }
-                None => {}
             }
 
             item.id
@@ -120,7 +111,6 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
                 _ => ccx.sess().bug("instantiate_inline: item has a \
                                  non-enum, non-struct parent")
             }
-            trans_item(ccx, &item);
             my_id
         }
         FoundAst::Found(&InlinedItem::TraitItem(_, ref trait_item)) => {
@@ -133,10 +123,10 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
             // the logic to do that already exists in `middle`. In order to
             // reuse that code, it needs to be able to look up the traits for
             // inlined items.
-            let ty_trait_item = ccx.tcx().impl_or_trait_item(fn_id).clone();
-            let trait_item_def_id = ccx.tcx().map.local_def_id(trait_item.id);
-            ccx.tcx().impl_or_trait_items.borrow_mut()
-                     .insert(trait_item_def_id, ty_trait_item);
+            let ty_trait_item = tcx.impl_or_trait_item(fn_id).clone();
+            let trait_item_def_id = tcx.map.local_def_id(trait_item.id);
+            tcx.impl_or_trait_items.borrow_mut()
+               .insert(trait_item_def_id, ty_trait_item);
 
             // If this is a default method, we can't look up the
             // impl type. But we aren't going to translate anyways, so
@@ -151,11 +141,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
 
             // Translate monomorphic impl methods immediately.
             if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node {
-                let impl_tpt = ccx.tcx().lookup_item_type(impl_did);
+                let impl_tpt = tcx.lookup_item_type(impl_did);
                 if impl_tpt.generics.types.is_empty() &&
                         sig.generics.ty_params.is_empty() {
-                    let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
-                    let llfn = get_item_val(ccx, impl_item.id);
+                    let empty_substs = tcx.mk_substs(Substs::trans_empty());
+                    let def_id = tcx.map.local_def_id(impl_item.id);
+                    let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
                     trans_fn(ccx,
                              &sig.decl,
                              body,
@@ -176,7 +167,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
         }
     };
 
-    let inline_def_id = ccx.tcx().map.local_def_id(inline_id);
+    let inline_def_id = tcx.map.local_def_id(inline_id);
     Some(inline_def_id)
 }
 
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index d246208ec1d..77df214d6dd 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -213,7 +213,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                     if out_type_size != 0 {
                         // FIXME #19925 Remove this hack after a release cycle.
                         let _ = unpack_datum!(bcx, expr::trans(bcx, &arg_exprs[0]));
-                        let llfn = Callee::def(ccx, def_id, substs, in_type).reify(ccx).val;
+                        let llfn = Callee::def(ccx, def_id, substs).reify(ccx).val;
                         let llfnty = val_ty(llfn);
                         let llresult = match dest {
                             expr::SaveIn(d) => d,
@@ -1208,6 +1208,7 @@ fn trans_gnu_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              dloc: DebugLoc) -> Block<'blk, 'tcx> {
     let llfn = get_rust_try_fn(bcx.fcx, &mut |bcx| {
         let ccx = bcx.ccx();
+        let tcx = ccx.tcx();
         let dloc = DebugLoc::None;
 
         // Translates the shims described above:
@@ -1228,10 +1229,11 @@ fn trans_gnu_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         // managed by the standard library.
 
         attributes::emit_uwtable(bcx.fcx.llfn, true);
-        let catch_pers = match bcx.tcx().lang_items.eh_personality_catch() {
-            Some(did) => callee::trans_fn_ref(ccx, did, ExprId(0),
-                                              bcx.fcx.param_substs).val,
-            None => bcx.tcx().sess.bug("eh_personality_catch not defined"),
+        let catch_pers = match tcx.lang_items.eh_personality_catch() {
+            Some(did) => {
+                Callee::def(ccx, did, tcx.mk_substs(Substs::empty())).reify(ccx).val
+            }
+            None => ccx.sess().bug("eh_personality_catch not defined"),
         };
 
         let then = bcx.fcx.new_temp_block("then");
@@ -1341,9 +1343,10 @@ fn generate_filter_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
     let tcx = ccx.tcx();
     let dloc = DebugLoc::None;
 
-    let rust_try_filter = match ccx.tcx().lang_items.msvc_try_filter() {
-        Some(did) => callee::trans_fn_ref(ccx, did, ExprId(0),
-                                          fcx.param_substs).val,
+    let rust_try_filter = match tcx.lang_items.msvc_try_filter() {
+        Some(did) => {
+            Callee::def(ccx, did, tcx.mk_substs(Substs::empty())).reify(ccx).val
+        }
         None => ccx.sess().bug("msvc_try_filter not defined"),
     };
 
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index da07a02bd3a..5b052a8e602 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -310,17 +310,9 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 let nullptr = C_null(Type::nil(ccx).ptr_to());
                 get_vtable_methods(ccx, id, substs)
                     .into_iter()
-                    .map(|opt_mth| {
-                        match opt_mth {
-                            Some(mth) => {
-                                trans_fn_ref_with_substs(ccx,
-                                                         mth.method.def_id,
-                                                         None,
-                                                         &mth.substs).val
-                            }
-                            None => nullptr
-                        }
-                    })
+                    .map(|opt_mth| opt_mth.map_or(nullptr, |mth| {
+                        Callee::def(ccx, mth.method.def_id, &mth.substs).reify(ccx).val
+                    }))
                     .collect::<Vec<_>>()
                     .into_iter()
             }
diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs
index 50283c0959c..1bbb2447e6a 100644
--- a/src/librustc_trans/trans/mir/block.rs
+++ b/src/librustc_trans/trans/mir/block.rs
@@ -163,7 +163,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
 
                 let (callee, fty) = match callee.ty.sty {
                     ty::TyFnDef(def_id, substs, f) => {
-                        (Callee::def(bcx.ccx(), def_id, substs, callee.ty), f)
+                        (Callee::def(bcx.ccx(), def_id, substs), f)
                     }
                     ty::TyFnPtr(f) => {
                         (Callee {
diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs
index 4b5f1566380..99c388f604b 100644
--- a/src/librustc_trans/trans/mir/rvalue.rs
+++ b/src/librustc_trans/trans/mir/rvalue.rs
@@ -201,7 +201,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         match operand.ty.sty {
                             ty::TyFnDef(def_id, substs, _) => {
                                 OperandValue::Immediate(
-                                    Callee::def(bcx.ccx(), def_id, substs, operand.ty)
+                                    Callee::def(bcx.ccx(), def_id, substs)
                                         .reify(bcx.ccx()).val)
                             }
                             _ => {
@@ -511,8 +511,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 if use_fmod {
                     let f64t = Type::f64(bcx.ccx());
                     let fty = Type::func(&[f64t, f64t], &f64t);
-                    let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty,
-                                                    tcx.types.f64);
+                    let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty);
                     if input_ty == tcx.types.f32 {
                         let lllhs = bcx.fpext(lhs, f64t);
                         let llrhs = bcx.fpext(rhs, f64t);