about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/trans/consts.rs11
-rw-r--r--src/librustc/middle/trans/expr.rs25
-rw-r--r--src/librustc/middle/trans/type_of.rs7
3 files changed, 29 insertions, 14 deletions
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index bcf796caa7a..d86d4c97c3b 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -407,6 +407,10 @@ pub fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
                     // variant or we wouldn't have gotten here -- the constant
                     // checker forbids paths that don't map to C-like enum
                     // variants.
+                    if ty::enum_is_univariant(cx.tcx, enum_did) {
+                        // Univariants have no discriminant field.
+                        C_struct(~[])
+                    } else {
                     let lldiscrim = base::get_discrim_val(cx, e.span,
                                                           enum_did,
                                                           variant_did);
@@ -418,6 +422,7 @@ pub fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
                     let padding = C_null(T_array(T_i8(), size));
                     C_struct(~[lldiscrim, padding])
                 }
+                }
                 Some(ast::def_struct(_)) => {
                     let ety = ty::expr_ty(cx.tcx, e);
                     let llty = type_of::type_of(cx, ety);
@@ -442,14 +447,14 @@ pub fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
                 }
             Some(ast::def_variant(tid, vid)) => {
                 let ety = ty::expr_ty(cx.tcx, e);
-                let degen = ty::enum_is_univariant(cx.tcx, tid);
+                let univar = ty::enum_is_univariant(cx.tcx, tid);
                 let size = machine::static_size_of_enum(cx, ety);
 
                 let discrim = base::get_discrim_val(cx, e.span, tid, vid);
                 let c_args = C_struct(args.map(|a| const_expr(cx, *a)));
 
                 // FIXME (#1645): enum body alignment is generaly wrong.
-                if !degen {
+                if !univar {
                     // Pad out the data to the size of its type_of;
                     // this is necessary if the enum is contained
                     // within an aggregate (tuple, struct, vector) so
@@ -464,8 +469,6 @@ pub fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef {
                     // without affecting its internal alignment or
                     // changing the alignment of the enum.
                     C_struct(~[discrim, C_packed_struct(~[c_args]), padding])
-                } else if size == 0 {
-                    C_struct(~[discrim])
                 } else {
                     C_struct(~[c_args])
                 }
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index cab2adc43fa..30ba0e7feee 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -674,12 +674,15 @@ fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr,
                 // N-ary variant.
                 let fn_data = callee::trans_fn_ref(bcx, vid, ref_expr.id);
                 return fn_data_to_datum(bcx, vid, fn_data, lldest);
-            } else {
+            } else if !ty::enum_is_univariant(ccx.tcx, tid) {
                 // Nullary variant.
                 let lldiscrimptr = GEPi(bcx, lldest, [0u, 0u]);
                 let lldiscrim = C_int(bcx.ccx(), variant_info.disr_val);
                 Store(bcx, lldiscrim, lldiscrimptr);
                 return bcx;
+            } else {
+                // Nullary univariant.
+                return bcx;
             }
         }
         ast::def_struct(*) => {
@@ -1591,10 +1594,22 @@ fn trans_imm_cast(bcx: block, expr: @ast::expr,
             {in: cast_enum, out: cast_integral} |
             {in: cast_enum, out: cast_float} => {
                 let bcx = bcx;
-                let llenumty = T_opaque_enum_ptr(ccx);
-                let av_enum = PointerCast(bcx, llexpr, llenumty);
-                let lldiscrim_a_ptr = GEPi(bcx, av_enum, [0u, 0u]);
-                let lldiscrim_a = Load(bcx, lldiscrim_a_ptr);
+                let in_tid = match ty::get(t_in).sty {
+                    ty::ty_enum(did, _) => did,
+                    _ => ccx.sess.bug(~"enum cast source is not enum")
+                };
+                let variants = ty::enum_variants(ccx.tcx, in_tid);
+                let lldiscrim_a = if variants.len() == 1 {
+                    // Univariants don't have a discriminant field,
+                    // because there's only one value it could have:
+                    C_integral(T_enum_discrim(ccx),
+                               variants[0].disr_val as u64, True)
+                } else {
+                    let llenumty = T_opaque_enum_ptr(ccx);
+                    let av_enum = PointerCast(bcx, llexpr, llenumty);
+                    let lldiscrim_a_ptr = GEPi(bcx, av_enum, [0u, 0u]);
+                    Load(bcx, lldiscrim_a_ptr)
+                };
                 match k_out {
                     cast_integral => int_cast(bcx, ll_t_out,
                                               val_ty(lldiscrim_a),
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index 84a19cd4c04..972f702c18a 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -242,14 +242,11 @@ pub fn fill_type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t,
     debug!("type_of_enum %?: %?", t, ty::get(t));
 
     let lltys = {
-        let degen = ty::enum_is_univariant(cx.tcx, did);
+        let univar = ty::enum_is_univariant(cx.tcx, did);
         let size = machine::static_size_of_enum(cx, t);
-        if !degen {
+        if !univar {
             ~[T_enum_discrim(cx), T_array(T_i8(), size)]
         }
-        else if size == 0u {
-            ~[T_enum_discrim(cx)]
-        }
         else {
             ~[T_array(T_i8(), size)]
         }