Auto merge of #56887 - emilio:enum-field-reordering, r=eddyb

Disable field reordering for repr(int).

This fixes the problem that the test in #56619 uncovers.

Closes #56619.
This commit is contained in:
bors 2018-12-22 20:35:30 +00:00
commit 2d3e909e4e
4 changed files with 33 additions and 26 deletions

View file

@ -2061,9 +2061,10 @@ impl ReprOptions {
}
/// Returns `true` if this `#[repr()]` should inhibit struct field reordering
/// optimizations, such as with repr(C) or repr(packed(1)).
/// optimizations, such as with repr(C), repr(packed(1)), or repr(<int>).
pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
!(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1)
self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.pack == 1 ||
self.int.is_some()
}
/// Returns true if this `#[repr()]` should inhibit union abi optimisations

View file

@ -20,11 +20,12 @@ use std::mem;
#[repr(C, u8)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum MyEnum {
A(u32), // Single primitive value
B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal
C, // Empty
D(Option<u32>), // Contains an enum
E(Duration), // Contains a struct
A(u32), // Single primitive value
B { x: u8, y: i16, z: u8 }, // Composite, and the offsets of `y` and `z`
// depend on tag being internal
C, // Empty
D(Option<u32>), // Contains an enum
E(Duration), // Contains a struct
}
#[repr(C)]
@ -44,14 +45,14 @@ union MyEnumPayload {
#[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E }
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32);
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 }
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 }
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option<u32>);
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration);
fn main() {
let result: Vec<Result<MyEnum, ()>> = vec![
Ok(MyEnum::A(17)),
Ok(MyEnum::B { x: 206, y: 1145 }),
Ok(MyEnum::B { x: 206, y: 1145, z: 78 }),
Ok(MyEnum::C),
Err(()),
Ok(MyEnum::D(Some(407))),
@ -63,7 +64,7 @@ fn main() {
// Binary serialized version of the above (little-endian)
let input: Vec<u8> = vec![
0, 17, 0, 0, 0,
1, 206, 121, 4,
1, 206, 121, 4, 78,
2,
8, /* invalid tag value */
3, 0, 151, 1, 0, 0,
@ -112,6 +113,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> {
MyEnumTag::B => {
dest.payload.B.x = read_u8(buf)?;
dest.payload.B.y = read_u16_le(buf)? as i16;
dest.payload.B.z = read_u8(buf)?;
}
MyEnumTag::C => {
/* do nothing */

View file

@ -20,11 +20,12 @@ use std::mem;
#[repr(C)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum MyEnum {
A(u32), // Single primitive value
B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal
C, // Empty
D(Option<u32>), // Contains an enum
E(Duration), // Contains a struct
A(u32), // Single primitive value
B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z`
// depend on tag being internal
C, // Empty
D(Option<u32>), // Contains an enum
E(Duration), // Contains a struct
}
#[repr(C)]
@ -44,14 +45,14 @@ union MyEnumPayload {
#[repr(C)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E }
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32);
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 }
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 }
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option<u32>);
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration);
fn main() {
let result: Vec<Result<MyEnum, ()>> = vec![
Ok(MyEnum::A(17)),
Ok(MyEnum::B { x: 206, y: 1145 }),
Ok(MyEnum::B { x: 206, y: 1145, z: 78 }),
Ok(MyEnum::C),
Err(()),
Ok(MyEnum::D(Some(407))),
@ -63,7 +64,7 @@ fn main() {
// Binary serialized version of the above (little-endian)
let input: Vec<u8> = vec![
0, 17, 0, 0, 0,
1, 206, 121, 4,
1, 206, 121, 4, 78,
2,
8, /* invalid tag value */
3, 0, 151, 1, 0, 0,
@ -112,6 +113,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> {
MyEnumTag::B => {
dest.payload.B.x = read_u8(buf)?;
dest.payload.B.y = read_u16_le(buf)? as i16;
dest.payload.B.z = read_u8(buf)?;
}
MyEnumTag::C => {
/* do nothing */

View file

@ -20,11 +20,12 @@ use std::mem;
#[repr(u8)]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum MyEnum {
A(u32), // Single primitive value
B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal
C, // Empty
D(Option<u32>), // Contains an enum
E(Duration), // Contains a struct
A(u32), // Single primitive value
B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z`
// depend on tag being internal
C, // Empty
D(Option<u32>), // Contains an enum
E(Duration), // Contains a struct
}
#[allow(non_snake_case)]
@ -39,7 +40,7 @@ union MyEnumRepr {
#[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E }
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(MyEnumTag, u32);
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16 }
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16, z: u8 }
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantC(MyEnumTag);
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(MyEnumTag, Option<u32>);
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(MyEnumTag, Duration);
@ -47,7 +48,7 @@ union MyEnumRepr {
fn main() {
let result: Vec<Result<MyEnum, ()>> = vec![
Ok(MyEnum::A(17)),
Ok(MyEnum::B { x: 206, y: 1145 }),
Ok(MyEnum::B { x: 206, y: 1145, z: 78 }),
Ok(MyEnum::C),
Err(()),
Ok(MyEnum::D(Some(407))),
@ -59,7 +60,7 @@ fn main() {
// Binary serialized version of the above (little-endian)
let input: Vec<u8> = vec![
0, 17, 0, 0, 0,
1, 206, 121, 4,
1, 206, 121, 4, 78,
2,
8, /* invalid tag value */
3, 0, 151, 1, 0, 0,
@ -108,6 +109,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> {
MyEnumTag::B => {
dest.B.x = read_u8(buf)?;
dest.B.y = read_u16_le(buf)? as i16;
dest.B.z = read_u8(buf)?;
}
MyEnumTag::C => {
/* do nothing */