diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs
index e83fe60f419a6..be6bb8689eefa 100644
--- a/src/librustc/mir/repr.rs
+++ b/src/librustc/mir/repr.rs
@@ -701,9 +701,9 @@ pub struct Constant<'tcx> {
 #[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum ItemKind {
     Constant,
+    /// This is any sort of callable (usually those that have a type of `fn(…) -> …`). This
+    /// includes functions, constructors, but not methods which have their own ItemKind.
     Function,
-    Struct,
-    Variant,
     Method,
 }
 
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 5cb12627d6ba8..46e6243c8bf30 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -519,51 +519,51 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
     let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs);
     // Otherwise there may be def_map borrow conflicts
     let def = cx.tcx.def_map.borrow()[&expr.id].full_def();
-    match def {
-        def::DefVariant(_, def_id, false) |
-        def::DefStruct(def_id) |
-        def::DefFn(def_id, _) |
-        def::DefMethod(def_id) => {
-            let kind = match def {
-                def::DefVariant(..) => ItemKind::Variant,
-                def::DefStruct(..) => ItemKind::Struct,
-                def::DefFn(..) => ItemKind::Function,
-                def::DefMethod(..) => ItemKind::Method,
-                _ => panic!()
-            };
-            ExprKind::Literal {
-                literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
+    let (def_id, kind) = match def {
+        // A variant constructor.
+        def::DefVariant(_, def_id, false) => (def_id, ItemKind::Function),
+        // A regular function.
+        def::DefFn(def_id, _) => (def_id, ItemKind::Function),
+        def::DefMethod(def_id) => (def_id, ItemKind::Method),
+        def::DefStruct(def_id) => {
+            match cx.tcx.node_id_to_type(expr.id).sty {
+                // A tuple-struct constructor.
+                ty::TyBareFn(..) => (def_id, ItemKind::Function),
+                // This is a special case: a unit struct which is used as a value. We return a
+                // completely different ExprKind here to account for this special case.
+                ty::TyStruct(adt_def, substs) => return ExprKind::Adt {
+                    adt_def: adt_def,
+                    variant_index: 0,
+                    substs: substs,
+                    fields: vec![],
+                    base: None
+                },
+                ref sty => panic!("unexpected sty: {:?}", sty)
             }
         },
         def::DefConst(def_id) |
         def::DefAssociatedConst(def_id) => {
             if let Some(v) = cx.try_const_eval_literal(expr) {
-                ExprKind::Literal { literal: v }
+                return ExprKind::Literal { literal: v };
             } else {
-                ExprKind::Literal {
-                    literal: Literal::Item {
-                        def_id: def_id,
-                        kind: ItemKind::Constant,
-                        substs: substs
-                    }
-                }
+                (def_id, ItemKind::Constant)
             }
         }
 
-
-        def::DefStatic(node_id, _) =>
-            ExprKind::StaticRef {
-                id: node_id,
-            },
+        def::DefStatic(node_id, _) => return ExprKind::StaticRef {
+            id: node_id,
+        },
 
         def @ def::DefLocal(..) |
-        def @ def::DefUpvar(..) =>
-            convert_var(cx, expr, def),
+        def @ def::DefUpvar(..) => return convert_var(cx, expr, def),
 
         def =>
             cx.tcx.sess.span_bug(
                 expr.span,
                 &format!("def `{:?}` not yet implemented", def)),
+    };
+    ExprKind::Literal {
+        literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
     }
 }
 
diff --git a/src/librustc_trans/trans/mir/did.rs b/src/librustc_trans/trans/mir/did.rs
index 368708d470bef..d4a7a7c8b48ff 100644
--- a/src/librustc_trans/trans/mir/did.rs
+++ b/src/librustc_trans/trans/mir/did.rs
@@ -39,9 +39,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                           did: DefId)
                           -> OperandRef<'tcx> {
         match kind {
-            ItemKind::Function |
-            ItemKind::Struct |
-            ItemKind::Variant => self.trans_fn_ref(bcx, ty, substs, did),
+            ItemKind::Function => self.trans_fn_ref(bcx, ty, substs, did),
             ItemKind::Method => match bcx.tcx().impl_or_trait_item(did).container() {
                 ty::ImplContainer(_) => self.trans_fn_ref(bcx, ty, substs, did),
                 ty::TraitContainer(tdid) => self.trans_static_method(bcx, ty, did, tdid, substs)
diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs
index 529e65dace04c..55a41201b2ba1 100644
--- a/src/librustc_trans/trans/mir/rvalue.rs
+++ b/src/librustc_trans/trans/mir/rvalue.rs
@@ -19,6 +19,7 @@ use trans::common::{self, Block, Result};
 use trans::debuginfo::DebugLoc;
 use trans::declare;
 use trans::expr;
+use trans::adt;
 use trans::machine;
 use trans::type_::Type;
 use trans::type_of;
@@ -26,21 +27,22 @@ use trans::tvec;
 
 use super::MirContext;
 use super::operand::{OperandRef, OperandValue};
+use super::lvalue::LvalueRef;
 
 impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
     pub fn trans_rvalue(&mut self,
                         bcx: Block<'bcx, 'tcx>,
-                        lldest: ValueRef,
+                        dest: LvalueRef<'tcx>,
                         rvalue: &mir::Rvalue<'tcx>)
                         -> Block<'bcx, 'tcx>
     {
-        debug!("trans_rvalue(lldest={}, rvalue={:?})",
-               bcx.val_to_string(lldest),
+        debug!("trans_rvalue(dest.llval={}, rvalue={:?})",
+               bcx.val_to_string(dest.llval),
                rvalue);
 
         match *rvalue {
             mir::Rvalue::Use(ref operand) => {
-                self.trans_operand_into(bcx, lldest, operand);
+                self.trans_operand_into(bcx, dest.llval, operand);
                 bcx
             }
 
@@ -49,7 +51,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                     // into-coerce of a thin pointer to a fat pointer - just
                     // use the operand path.
                     let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
-                    self.store_operand(bcx, lldest, temp);
+                    self.store_operand(bcx, dest.llval, temp);
                     return bcx;
                 }
 
@@ -72,12 +74,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         base::store_ty(bcx, llval, lltemp, operand.ty);
                         base::coerce_unsized_into(bcx,
                                                   lltemp, operand.ty,
-                                                  lldest, cast_ty);
+                                                  dest.llval, cast_ty);
                     }
                     OperandValue::Ref(llref) => {
                         base::coerce_unsized_into(bcx,
                                                   llref, operand.ty,
-                                                  lldest, cast_ty);
+                                                  dest.llval, cast_ty);
                     }
                 }
                 bcx
@@ -86,20 +88,31 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
             mir::Rvalue::Repeat(ref elem, ref count) => {
                 let elem = self.trans_operand(bcx, elem);
                 let size = self.trans_constant(bcx, count).immediate();
-                let base = expr::get_dataptr(bcx, lldest);
+                let base = expr::get_dataptr(bcx, dest.llval);
                 tvec::iter_vec_raw(bcx, base, elem.ty, size, |bcx, llslot, _| {
                     self.store_operand(bcx, llslot, elem);
                     bcx
                 })
             }
 
-            mir::Rvalue::Aggregate(_, ref operands) => {
-                for (i, operand) in operands.iter().enumerate() {
-                    // Note: perhaps this should be StructGep, but
-                    // note that in some cases the values here will
-                    // not be structs but arrays.
-                    let lldest_i = build::GEPi(bcx, lldest, &[0, i]);
-                    self.trans_operand_into(bcx, lldest_i, operand);
+            mir::Rvalue::Aggregate(ref kind, ref operands) => {
+                match *kind {
+                    // Unit struct, which is translated very differently compared to any other
+                    // aggregate
+                    mir::AggregateKind::Adt(adt_def, 0, _)
+                    if adt_def.struct_variant().kind() == ty::VariantKind::Unit => {
+                        let repr = adt::represent_type(bcx.ccx(), dest.ty.to_ty(bcx.tcx()));
+                        adt::trans_set_discr(bcx, &*repr, dest.llval, 0);
+                    },
+                    _ => {
+                        for (i, operand) in operands.iter().enumerate() {
+                            // Note: perhaps this should be StructGep, but
+                            // note that in some cases the values here will
+                            // not be structs but arrays.
+                            let lldest_i = build::GEPi(bcx, dest.llval, &[0, i]);
+                            self.trans_operand_into(bcx, lldest_i, operand);
+                        }
+                    }
                 }
                 bcx
             }
@@ -113,9 +126,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 let llbase1 = build::GEPi(bcx, llbase, &[from_start]);
                 let adj = common::C_uint(ccx, from_start + from_end);
                 let lllen1 = build::Sub(bcx, lllen, adj, DebugLoc::None);
-                let lladdrdest = expr::get_dataptr(bcx, lldest);
+                let lladdrdest = expr::get_dataptr(bcx, dest.llval);
                 build::Store(bcx, llbase1, lladdrdest);
-                let llmetadest = expr::get_meta(bcx, lldest);
+                let llmetadest = expr::get_meta(bcx, dest.llval);
                 build::Store(bcx, lllen1, llmetadest);
                 bcx
             }
@@ -127,7 +140,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
             _ => {
                 assert!(rvalue_creates_operand(rvalue));
                 let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
-                self.store_operand(bcx, lldest, temp);
+                self.store_operand(bcx, dest.llval, temp);
                 bcx
             }
         }
diff --git a/src/librustc_trans/trans/mir/statement.rs b/src/librustc_trans/trans/mir/statement.rs
index 9894626e284a2..dae0d3b55c0ba 100644
--- a/src/librustc_trans/trans/mir/statement.rs
+++ b/src/librustc_trans/trans/mir/statement.rs
@@ -31,7 +31,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         let index = index as usize;
                         match self.temps[index as usize] {
                             TempRef::Lvalue(tr_dest) => {
-                                self.trans_rvalue(bcx, tr_dest.llval, rvalue)
+                                self.trans_rvalue(bcx, tr_dest, rvalue)
                             }
                             TempRef::Operand(None) => {
                                 let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue);
@@ -47,7 +47,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                     }
                     _ => {
                         let tr_dest = self.trans_lvalue(bcx, lvalue);
-                        self.trans_rvalue(bcx, tr_dest.llval, rvalue)
+                        self.trans_rvalue(bcx, tr_dest, rvalue)
                     }
                 }
             }
diff --git a/src/test/run-pass/mir_refs_correct.rs b/src/test/run-pass/mir_refs_correct.rs
index 2da1a75870964..9b349c0e4e21b 100644
--- a/src/test/run-pass/mir_refs_correct.rs
+++ b/src/test/run-pass/mir_refs_correct.rs
@@ -14,6 +14,8 @@
 extern crate mir_external_refs as ext;
 
 struct S(u8);
+#[derive(Debug, PartialEq, Eq)]
+struct Unit;
 
 impl S {
     fn hey() -> u8 { 42 }
@@ -175,6 +177,11 @@ fn t20() -> fn(u64, u32)->(u64, u32) {
     <u32 as T<_, _>>::staticmeth
 }
 
+#[rustc_mir]
+fn t21() -> Unit {
+    Unit
+}
+
 fn main(){
     unsafe {
         assert_eq!(t1()(), regular());
@@ -214,5 +221,6 @@ fn main(){
         assert_eq!(t18()(50u64, 5u64), F::f(50u64, 5u64));
         assert_eq!(t19()(322u64, 2u32), F::f(322u64, 2u32));
         assert_eq!(t20()(123u64, 38u32), <u32 as T<_, _>>::staticmeth(123, 38));
+        assert_eq!(t21(), Unit);
     }
 }