Skip to content

Omit discriminant from nullary univariant enums. #4866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/librustc/middle/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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
Expand All @@ -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])
}
Expand Down
25 changes: 20 additions & 5 deletions src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(*) => {
Expand Down Expand Up @@ -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),
Expand Down
7 changes: 2 additions & 5 deletions src/librustc/middle/trans/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
}
Expand Down