about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2017-02-07 22:46:21 +0100
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2017-03-18 02:52:07 +0200
commit0af3775dd2c93cdaf8902f83eb21037e474e058f (patch)
treef6eff24a41ef82f9a95b57c84febb8765948cd74 /src
parenta559452b05c20041a27f518d262573c56b876b64 (diff)
downloadrust-0af3775dd2c93cdaf8902f83eb21037e474e058f.tar.gz
rust-0af3775dd2c93cdaf8902f83eb21037e474e058f.zip
translate tuple-variant constructors using MIR
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ty/mod.rs13
-rw-r--r--src/librustc_metadata/encoder.rs4
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_mir/mir_map.rs63
-rw-r--r--src/librustc_mir/shim.rs109
-rw-r--r--src/librustc_trans/base.rs78
-rw-r--r--src/librustc_trans/callee.rs33
-rw-r--r--src/librustc_trans/collector.rs19
-rw-r--r--src/librustc_trans/common.rs10
-rw-r--r--src/librustc_trans/mir/block.rs6
-rw-r--r--src/librustc_trans/trans_item.rs16
11 files changed, 215 insertions, 138 deletions
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 3c37c7353d6..360fa24bf36 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1264,10 +1264,17 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
                                                     def_id,
                                                     ROOT_CODE_EXTENT)
             }
-            _ => {
+            Some(hir_map::NodeStructCtor(..)) |
+            Some(hir_map::NodeVariant(..)) => {
+                let def_id = tcx.hir.local_def_id(id);
+                tcx.construct_parameter_environment(tcx.hir.span(id),
+                                                    def_id,
+                                                    ROOT_CODE_EXTENT)
+            }
+            it => {
                 bug!("ParameterEnvironment::from_item(): \
-                      `{}` is not an item",
-                     tcx.hir.node_to_string(id))
+                      `{}` = {:?} is unsupported",
+                     tcx.hir.node_to_string(id), it)
             }
         }
     }
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 0c31e30671d..044ed529ef7 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -293,7 +293,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             predicates: Some(self.encode_predicates(def_id)),
 
             ast: None,
-            mir: None,
+            mir: self.encode_mir(def_id),
         }
     }
 
@@ -426,7 +426,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             predicates: Some(self.encode_predicates(def_id)),
 
             ast: None,
-            mir: None,
+            mir: self.encode_mir(def_id),
         }
     }
 
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index f21f1881c83..19028bfa531 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -22,6 +22,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 
 #![feature(associated_consts)]
 #![feature(box_patterns)]
+#![feature(box_syntax)]
 #![feature(i128_type)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
@@ -50,6 +51,7 @@ pub mod callgraph;
 pub mod def_use;
 pub mod graphviz;
 mod hair;
+mod shim;
 pub mod mir_map;
 pub mod pretty;
 pub mod transform;
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
index 58f23a5c81b..3fa7131a2b6 100644
--- a/src/librustc_mir/mir_map.rs
+++ b/src/librustc_mir/mir_map.rs
@@ -22,6 +22,7 @@ use rustc::dep_graph::DepNode;
 use rustc::mir::Mir;
 use rustc::mir::transform::MirSource;
 use rustc::mir::visit::MutVisitor;
+use shim;
 use pretty;
 use hair::cx::Cx;
 
@@ -30,6 +31,7 @@ use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::ty::subst::Substs;
 use rustc::hir;
+use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use syntax::abi::Abi;
 use syntax::ast;
 use syntax_pos::Span;
@@ -44,6 +46,31 @@ pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
             tcx.item_mir(body_owner_def_id);
         });
+
+        // Tuple struct/variant constructors don't have a BodyId, so we need
+        // to build them separately.
+        struct GatherCtors<'a, 'tcx: 'a> {
+            tcx: TyCtxt<'a, 'tcx, 'tcx>
+        }
+        impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> {
+            fn visit_variant_data(&mut self,
+                                  v: &'tcx hir::VariantData,
+                                  _: ast::Name,
+                                  _: &'tcx hir::Generics,
+                                  _: ast::NodeId,
+                                  _: Span) {
+                if let hir::VariantData::Tuple(_, node_id) = *v {
+                    self.tcx.item_mir(self.tcx.hir.local_def_id(node_id));
+                }
+                intravisit::walk_struct_def(self, v)
+            }
+            fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
+                NestedVisitorMap::None
+            }
+        }
+        tcx.visit_all_item_likes_in_krate(DepNode::Mir, &mut GatherCtors {
+            tcx: tcx
+        }.as_deep_visitor());
     }
 }
 
@@ -95,6 +122,10 @@ fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
                 _ => hir::BodyId { node_id: expr.id }
             }
         }
+        hir::map::NodeVariant(variant) =>
+            return create_constructor_shim(tcx, id, &variant.node.data),
+        hir::map::NodeStructCtor(ctor) =>
+            return create_constructor_shim(tcx, id, ctor),
         _ => unsupported()
     };
 
@@ -180,6 +211,38 @@ impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
     }
 }
 
+fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     ctor_id: ast::NodeId,
+                                     v: &'tcx hir::VariantData)
+                                     -> &'tcx RefCell<Mir<'tcx>>
+{
+    let span = tcx.hir.span(ctor_id);
+    if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
+        let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id);
+        tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
+            let (mut mir, src) =
+                shim::build_adt_ctor(&infcx, ctor_id, fields, span);
+
+            // Convert the Mir to global types.
+            let tcx = infcx.tcx.global_tcx();
+            let mut globalizer = GlobalizeMir {
+                tcx: tcx,
+                span: mir.span
+            };
+            globalizer.visit_mir(&mut mir);
+            let mir = unsafe {
+                mem::transmute::<Mir, Mir<'tcx>>(mir)
+            };
+
+            pretty::dump_mir(tcx, "mir_map", &0, src, &mir);
+
+            tcx.alloc_mir(mir)
+        })
+    } else {
+        span_bug!(span, "attempting to create MIR for non-tuple variant {:?}", v);
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
 
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
new file mode 100644
index 00000000000..3705a317715
--- /dev/null
+++ b/src/librustc_mir/shim.rs
@@ -0,0 +1,109 @@
+// Copyright 2016 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.
+
+use rustc::hir;
+use rustc::infer;
+use rustc::mir::*;
+use rustc::mir::transform::MirSource;
+use rustc::ty;
+
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+
+use syntax::ast;
+use syntax_pos::Span;
+
+use std::iter;
+
+fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>)
+    -> IndexVec<Local, LocalDecl<'tcx>>
+{
+    iter::once(LocalDecl {
+        mutability: Mutability::Mut,
+        ty: sig.output(),
+        name: None,
+        source_info: None
+    }).chain(sig.inputs().iter().map(|ity| LocalDecl {
+        mutability: Mutability::Not,
+        ty: *ity,
+        name: None,
+        source_info: None,
+    })).collect()
+}
+
+pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
+                                      ctor_id: ast::NodeId,
+                                      fields: &[hir::StructField],
+                                      span: Span)
+                                      -> (Mir<'tcx>, MirSource)
+{
+    let tcx = infcx.tcx;
+    let def_id = tcx.hir.local_def_id(ctor_id);
+    let sig = match tcx.item_type(def_id).sty {
+        ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty)
+            .expect("LBR in ADT constructor signature"),
+        _ => bug!("unexpected type for ctor {:?}", def_id)
+    };
+    let sig = tcx.erase_regions(&sig);
+
+    let (adt_def, substs) = match sig.output().sty {
+        ty::TyAdt(adt_def, substs) => (adt_def, substs),
+        _ => bug!("unexpected type for ADT ctor {:?}", sig.output())
+    };
+
+    debug!("build_ctor: def_id={:?} sig={:?} fields={:?}", def_id, sig, fields);
+
+    let local_decls = local_decls_for_sig(&sig);
+
+    let source_info = SourceInfo {
+        span: span,
+        scope: ARGUMENT_VISIBILITY_SCOPE
+    };
+
+    let variant_no = if adt_def.is_enum() {
+        adt_def.variant_index_with_id(def_id)
+    } else {
+        0
+    };
+
+    // return = ADT(arg0, arg1, ...); return
+    let start_block = BasicBlockData {
+        statements: vec![Statement {
+            source_info: source_info,
+            kind: StatementKind::Assign(
+                Lvalue::Local(RETURN_POINTER),
+                Rvalue::Aggregate(
+                    AggregateKind::Adt(adt_def, variant_no, substs, None),
+                    (1..sig.inputs().len()+1).map(|i| {
+                        Operand::Consume(Lvalue::Local(Local::new(i)))
+                    }).collect()
+                )
+            )
+        }],
+        terminator: Some(Terminator {
+            source_info: source_info,
+            kind: TerminatorKind::Return,
+        }),
+        is_cleanup: false
+    };
+
+    let mir = Mir::new(
+        IndexVec::from_elem_n(start_block, 1),
+        IndexVec::from_elem_n(
+            VisibilityScopeData { span: span, parent_scope: None }, 1
+        ),
+        IndexVec::new(),
+        sig.output(),
+        local_decls,
+        sig.inputs().len(),
+        vec![],
+        span
+    );
+    (mir, MirSource::Fn(ctor_id))
+}
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 1b43491e73c..fe2b21895cc 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -34,10 +34,8 @@ use back::linker::LinkerInfo;
 use back::symbol_export::{self, ExportedSymbols};
 use llvm::{Linkage, ValueRef, Vector, get_param};
 use llvm;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::hir::def_id::LOCAL_CRATE;
 use middle::lang_items::StartFnLangItem;
-use rustc::ty::subst::Substs;
-use rustc::mir::tcx::LvalueTy;
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
@@ -47,9 +45,8 @@ use rustc::util::common::time;
 use session::config::{self, NoDebugInfo};
 use rustc_incremental::IncrementalHashesMap;
 use session::{self, DataTypeKind, Session};
-use abi::{self, FnType};
+use abi;
 use mir::lvalue::LvalueRef;
-use adt;
 use attributes;
 use builder::Builder;
 use callee::{Callee};
@@ -65,7 +62,7 @@ use context::{SharedCrateContext, CrateContextList};
 use debuginfo;
 use declare;
 use machine;
-use machine::{llalign_of_min, llsize_of};
+use machine::llsize_of;
 use meth;
 use mir;
 use monomorphize::{self, Instance};
@@ -76,7 +73,6 @@ use trans_item::{TransItem, DefPathBasedNames};
 use type_::Type;
 use type_of;
 use value::Value;
-use Disr;
 use util::nodemap::{NodeSet, FxHashMap, FxHashSet};
 
 use libc::c_uint;
@@ -615,72 +611,6 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance
     mir::trans_mir(ccx, lldecl, &mir, instance, sig);
 }
 
-pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                 def_id: DefId,
-                                 substs: &'tcx Substs<'tcx>,
-                                 disr: Disr,
-                                 llfn: ValueRef) {
-    attributes::inline(llfn, attributes::InlineAttr::Hint);
-    attributes::set_frame_pointer_elimination(ccx, llfn);
-
-    let ctor_ty = common::def_ty(ccx.shared(), def_id, substs);
-    let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&ctor_ty.fn_sig());
-    let fn_ty = FnType::new(ccx, sig, &[]);
-
-    let bcx = Builder::new_block(ccx, llfn, "entry-block");
-    if !fn_ty.ret.is_ignore() {
-        // But if there are no nested returns, we skip the indirection
-        // and have a single retslot
-        let dest = if fn_ty.ret.is_indirect() {
-            get_param(llfn, 0)
-        } else {
-            // We create an alloca to hold a pointer of type `ret.original_ty`
-            // which will hold the pointer to the right alloca which has the
-            // final ret value
-            bcx.alloca(fn_ty.ret.memory_ty(ccx), "sret_slot")
-        };
-        // Can return unsized value
-        let mut dest_val = LvalueRef::new_sized_ty(dest, sig.output(), Alignment::AbiAligned);
-        dest_val.ty = LvalueTy::Downcast {
-            adt_def: sig.output().ty_adt_def().unwrap(),
-            substs: substs,
-            variant_index: disr.0 as usize,
-        };
-        let mut llarg_idx = fn_ty.ret.is_indirect() as usize;
-        let mut arg_idx = 0;
-        for (i, arg_ty) in sig.inputs().iter().enumerate() {
-            let (lldestptr, _) = dest_val.trans_field_ptr(&bcx, i);
-            let arg = &fn_ty.args[arg_idx];
-            arg_idx += 1;
-            if common::type_is_fat_ptr(bcx.ccx, arg_ty) {
-                let meta = &fn_ty.args[arg_idx];
-                arg_idx += 1;
-                arg.store_fn_arg(&bcx, &mut llarg_idx, get_dataptr(&bcx, lldestptr));
-                meta.store_fn_arg(&bcx, &mut llarg_idx, get_meta(&bcx, lldestptr));
-            } else {
-                arg.store_fn_arg(&bcx, &mut llarg_idx, lldestptr);
-            }
-        }
-        adt::trans_set_discr(&bcx, sig.output(), dest, disr);
-
-        if fn_ty.ret.is_indirect() {
-            bcx.ret_void();
-            return;
-        }
-
-        if let Some(cast_ty) = fn_ty.ret.cast {
-            bcx.ret(bcx.load(
-                bcx.pointercast(dest, cast_ty.ptr_to()),
-                Some(llalign_of_min(ccx, fn_ty.ret.ty))
-            ));
-        } else {
-            bcx.ret(bcx.load(dest, None))
-        }
-    } else {
-        bcx.ret_void();
-    }
-}
-
 pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
     // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
     // applicable to variable declarations and may not really make sense for
@@ -721,7 +651,7 @@ pub fn set_link_section(ccx: &CrateContext,
 }
 
 /// Create the `main` function which will initialise the rust runtime and call
-/// users’ main function.
+/// users main function.
 pub fn maybe_create_entry_wrapper(ccx: &CrateContext) {
     let (main_def_id, span) = match *ccx.sess().entry_fn.borrow() {
         Some((id, span)) => {
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index 762aaf1ce1d..a5b42a973cf 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -22,7 +22,6 @@ use rustc::ty::subst::{Substs, Subst};
 use rustc::traits;
 use abi::{Abi, FnType};
 use attributes;
-use base;
 use builder::Builder;
 use common::{self, CrateContext};
 use cleanup::CleanupScope;
@@ -35,7 +34,6 @@ use meth;
 use monomorphize::Instance;
 use trans_item::TransItem;
 use type_of;
-use Disr;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::hir;
 use std::iter;
@@ -46,9 +44,6 @@ use mir::lvalue::Alignment;
 
 #[derive(Debug)]
 pub enum CalleeData {
-    /// Constructor for enum variant/tuple-like-struct.
-    NamedTupleConstructor(Disr),
-
     /// Function pointer.
     Fn(ValueRef),
 
@@ -92,16 +87,6 @@ impl<'tcx> Callee<'tcx> {
             }
         }
 
-        // FIXME(eddyb) Detect ADT constructors more efficiently.
-        if let Some(adt_def) = fn_ty.fn_ret().skip_binder().ty_adt_def() {
-            if let Some(i) = adt_def.variants.iter().position(|v| def_id == v.did) {
-                return Callee {
-                    data: NamedTupleConstructor(Disr::for_variant(tcx, adt_def, i)),
-                    ty: fn_ty
-                };
-            }
-        }
-
         let (llfn, ty) = get_fn(ccx, def_id, substs);
         Callee::ptr(llfn, ty)
     }
@@ -185,24 +170,6 @@ impl<'tcx> Callee<'tcx> {
         match self.data {
             Fn(llfn) => llfn,
             Virtual(_) => meth::trans_object_shim(ccx, self),
-            NamedTupleConstructor(disr) => match self.ty.sty {
-                ty::TyFnDef(def_id, substs, _) => {
-                    let instance = Instance::new(def_id, substs);
-                    if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
-                        return llfn;
-                    }
-
-                    let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
-                                                              TransItem::Fn(instance));
-                    assert!(!ccx.codegen_unit().contains_item(&TransItem::Fn(instance)));
-                    let lldecl = declare::define_internal_fn(ccx, &sym, self.ty);
-                    base::trans_ctor_shim(ccx, def_id, substs, disr, lldecl);
-                    ccx.instances().borrow_mut().insert(instance, lldecl);
-
-                    lldecl
-                }
-                _ => bug!("expected fn item type, found {}", self.ty)
-            },
             Intrinsic => bug!("intrinsic {} getting reified", self.ty)
         }
     }
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 8d1db38999c..5e6b10f826c 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -630,14 +630,15 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                                               -> bool {
             match tcx.item_type(def_id).sty {
                 ty::TyFnDef(def_id, _, _) => {
-                    // Some constructors also have type TyFnDef but they are
-                    // always instantiated inline and don't result in a
-                    // translation item. Same for FFI functions.
+                    // foreign items are linked from another library, not
+                    // translated locally.
                     if let Some(hir_map::NodeForeignItem(_)) = tcx.hir.get_if_local(def_id) {
                         return false;
                     }
                 }
-                ty::TyClosure(..) => {}
+                ty::TyClosure(..) => {
+                    // TODO: trans items for closures
+                }
                 _ => return false
             }
 
@@ -697,16 +698,6 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
 fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   def_id: DefId)
                                   -> bool {
-    if let ty::TyFnDef(_, _, sig) = tcx.item_type(def_id).sty {
-        if let Some(adt_def) = sig.output().skip_binder().ty_adt_def() {
-            if adt_def.variants.iter().any(|v| def_id == v.did) {
-                // HACK: ADT constructors are translated in-place and
-                // do not have a trans-item.
-                return false;
-            }
-        }
-    }
-
     if def_id.is_local() {
         true
     } else {
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index a509587f80f..0e536d58a56 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -37,6 +37,7 @@ use libc::{c_uint, c_char};
 use std::iter;
 
 use syntax::ast;
+use syntax::attr;
 use syntax::symbol::InternedString;
 use syntax_pos::Span;
 
@@ -601,8 +602,13 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 }
 
-pub fn is_closure(tcx: TyCtxt, def_id: DefId) -> bool {
-    tcx.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
+pub fn requests_inline(tcx: TyCtxt, def_id: DefId) -> bool {
+    match tcx.def_key(def_id).disambiguated_data.data {
+        DefPathData::StructCtor |
+        DefPathData::EnumVariant(..) |
+        DefPathData::ClosureExpr => true,
+        _ => attr::requests_inline(&tcx.get_attrs(def_id)[..]),
+    }
 }
 
 /// Given a DefId and some Substs, produces the monomorphic item type.
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 9d40419d338..2f1a2c9134c 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -16,7 +16,7 @@ use rustc::ty::{self, layout, TypeFoldable};
 use rustc::mir;
 use abi::{Abi, FnType, ArgType};
 use base::{self, Lifetime};
-use callee::{Callee, CalleeData, Fn, Intrinsic, NamedTupleConstructor, Virtual};
+use callee::{Callee, CalleeData, Fn, Intrinsic, Virtual};
 use builder::Builder;
 use common::{self, Funclet};
 use common::{C_bool, C_str_slice, C_struct, C_u32, C_undef};
@@ -491,10 +491,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 }
 
                 let fn_ptr = match callee.data {
-                    NamedTupleConstructor(_) => {
-                        // FIXME translate this like mir::Rvalue::Aggregate.
-                        callee.reify(bcx.ccx)
-                    }
                     Intrinsic => {
                         use intrinsic::trans_intrinsic_call;
 
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index d19f04b9554..5ec9c2a5995 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -26,6 +26,7 @@ use monomorphize::Instance;
 use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
+use rustc::hir::map::definitions::DefPathData;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::subst::Substs;
 use rustc_const_eval::fatal_const_eval_err;
@@ -178,9 +179,14 @@ impl<'a, 'tcx> TransItem<'tcx> {
             llvm::SetUniqueComdat(ccx.llmod(), lldecl);
         }
 
-        if let ty::TyClosure(..) = mono_ty.sty {
-            // set an inline hint for all closures
-            attributes::inline(lldecl, attributes::InlineAttr::Hint);
+        debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance);
+        match ccx.tcx().def_key(instance.def).disambiguated_data.data {
+            DefPathData::StructCtor |
+            DefPathData::EnumVariant(..) |
+            DefPathData::ClosureExpr => {
+                attributes::inline(lldecl, attributes::InlineAttr::Hint);
+            }
+            _ => {}
         }
 
         attributes::from_fn_attrs(ccx, &attrs, lldecl);
@@ -252,8 +258,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
         match *self {
             TransItem::Fn(ref instance) => {
                 if self.explicit_linkage(tcx).is_none() &&
-                   (common::is_closure(tcx, instance.def) ||
-                    attr::requests_inline(&tcx.get_attrs(instance.def)[..])) {
+                    common::requests_inline(tcx, instance.def)
+                {
                     InstantiationMode::LocalCopy
                 } else {
                     InstantiationMode::GloballyShared