diff options
| author | Anthony Ramine <n.oxyde@gmail.com> | 2018-03-30 15:49:56 +0200 |
|---|---|---|
| committer | Anthony Ramine <n.oxyde@gmail.com> | 2018-04-26 16:22:18 +0200 |
| commit | 8f36804c00ca11ca9b4ed111dc4b4066b940508e (patch) | |
| tree | 1bab393e295a519c8f6ac71c1a91b13e58ba9738 /src | |
| parent | 7bfe3ae00a36e8162e2f8f5b47eb7127562e1d17 (diff) | |
| download | rust-8f36804c00ca11ca9b4ed111dc4b4066b940508e.tar.gz rust-8f36804c00ca11ca9b4ed111dc4b4066b940508e.zip | |
Treat repr(Rust) univariant fieldless enums as a ZST (fixes #15747)
This makes all those enums be represented the same way:
```rust
enum A1 { B1 }
enum A2 { B2 = 0 }
enum A3 { B3, C3(!) }
```
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/ty/layout.rs | 9 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/eval_context.rs | 22 | ||||
| -rw-r--r-- | src/librustc_trans/mir/place.rs | 5 | ||||
| -rw-r--r-- | src/librustc_trans/mir/rvalue.rs | 16 | ||||
| -rw-r--r-- | src/test/run-pass/type-sizes.rs | 33 |
5 files changed, 78 insertions, 7 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 77e2e9447f1..7dec180c5a7 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1451,11 +1451,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { // Only one variant is inhabited. (inh_second.is_none() && // Representation optimizations are allowed. - !def.repr.inhibit_enum_layout_opt() && - // Inhabited variant either has data ... - (!variants[inh_first.unwrap()].is_empty() || - // ... or there other, uninhabited, variants. - variants.len() > 1)); + !def.repr.inhibit_enum_layout_opt()); if is_struct { // Struct, or univariant enum equivalent to a struct. // (Typechecking will reject discriminant-sizing attrs.) @@ -1489,6 +1485,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { return Ok(tcx.intern_layout(st)); } + // The current code for niche-filling relies on variant indices + // instead of actual discriminants, so dataful enums with + // explicit discriminants (RFC #2363) would misbehave. let no_explicit_discriminants = def.variants.iter().enumerate() .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i)); diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index a7cd044cec0..00f90573682 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -669,6 +669,23 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M (Value::ByVal(_), _) => bug!("expected fat ptr"), } } else { + let src_layout = self.layout_of(src.ty)?; + match src_layout.variants { + layout::Variants::Single { index } => { + if let Some(def) = src.ty.ty_adt_def() { + let discr_val = def + .discriminant_for_variant(*self.tcx, index) + .val; + return self.write_primval( + dest, + PrimVal::Bytes(discr_val), + dest_ty); + } + } + layout::Variants::Tagged { .. } | + layout::Variants::NicheFilling { .. } => {}, + } + let src_val = self.value_to_primval(src)?; let dest_val = self.cast_primval(src_val, src.ty, dest_ty)?; let valty = ValTy { @@ -856,7 +873,10 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M match layout.variants { layout::Variants::Single { index } => { - return Ok(index as u128); + let discr_val = ty.ty_adt_def().map_or( + index as u128, + |def| def.discriminant_for_variant(*self.tcx, index).val); + return Ok(discr_val); } layout::Variants::Tagged { .. } | layout::Variants::NicheFilling { .. } => {}, diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs index c39612e3ab0..b8b0c019ca6 100644 --- a/src/librustc_trans/mir/place.rs +++ b/src/librustc_trans/mir/place.rs @@ -269,7 +269,10 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } match self.layout.variants { layout::Variants::Single { index } => { - return C_uint(cast_to, index as u64); + let discr_val = self.layout.ty.ty_adt_def().map_or( + index as u128, + |def| def.discriminant_for_variant(bx.cx.tcx, index).val); + return C_uint_big(cast_to, discr_val); } layout::Variants::Tagged { .. } | layout::Variants::NicheFilling { .. } => {}, diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 245f3ec11c9..c932777402e 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -278,6 +278,22 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { .expect("bad input type for cast"); let r_t_out = CastTy::from_ty(cast.ty).expect("bad output type for cast"); let ll_t_in = operand.layout.immediate_llvm_type(bx.cx); + match operand.layout.variants { + layout::Variants::Single { index } => { + if let Some(def) = operand.layout.ty.ty_adt_def() { + let discr_val = def + .discriminant_for_variant(bx.cx.tcx, index) + .val; + let discr = C_uint_big(ll_t_out, discr_val); + return (bx, OperandRef { + val: OperandValue::Immediate(discr), + layout: cast, + }); + } + } + layout::Variants::Tagged { .. } | + layout::Variants::NicheFilling { .. } => {}, + } let llval = operand.immediate(); let mut signed = false; diff --git a/src/test/run-pass/type-sizes.rs b/src/test/run-pass/type-sizes.rs index 7bd9a1703ee..a47f082b9c3 100644 --- a/src/test/run-pass/type-sizes.rs +++ b/src/test/run-pass/type-sizes.rs @@ -43,6 +43,31 @@ enum ReorderedEnum { B(u8, u16, u8), } +enum EnumEmpty {} + +enum EnumSingle1 { + A, +} + +enum EnumSingle2 { + A = 42 as isize, +} + +enum EnumSingle3 { + A, + B(!), +} + +#[repr(u8)] +enum EnumSingle4 { + A, +} + +#[repr(u8)] +enum EnumSingle5 { + A = 42 as u8, +} + enum NicheFilledEnumWithInhabitedVariant { A(&'static ()), B(&'static (), !), @@ -74,5 +99,13 @@ pub fn main() { assert_eq!(size_of::<e3>(), 4 as usize); assert_eq!(size_of::<ReorderedStruct>(), 4); assert_eq!(size_of::<ReorderedEnum>(), 6); + + assert_eq!(size_of::<EnumEmpty>(), 0); + assert_eq!(size_of::<EnumSingle1>(), 0); + assert_eq!(size_of::<EnumSingle2>(), 0); + assert_eq!(size_of::<EnumSingle3>(), 0); + assert_eq!(size_of::<EnumSingle4>(), 1); + assert_eq!(size_of::<EnumSingle5>(), 1); + assert_eq!(size_of::<NicheFilledEnumWithInhabitedVariant>(), size_of::<&'static ()>()); } |
