Skip to content

Commit 2d3e909

Browse files
committed
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.
2 parents 9723a49 + d84bdba commit 2d3e909

File tree

4 files changed

+33
-26
lines changed

4 files changed

+33
-26
lines changed

src/librustc/ty/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2061,9 +2061,10 @@ impl ReprOptions {
20612061
}
20622062

20632063
/// Returns `true` if this `#[repr()]` should inhibit struct field reordering
2064-
/// optimizations, such as with repr(C) or repr(packed(1)).
2064+
/// optimizations, such as with repr(C), repr(packed(1)), or repr(<int>).
20652065
pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
2066-
!(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1)
2066+
self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.pack == 1 ||
2067+
self.int.is_some()
20672068
}
20682069

20692070
/// Returns true if this `#[repr()]` should inhibit union abi optimisations

src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ use std::mem;
2020
#[repr(C, u8)]
2121
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
2222
enum MyEnum {
23-
A(u32), // Single primitive value
24-
B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal
25-
C, // Empty
26-
D(Option<u32>), // Contains an enum
27-
E(Duration), // Contains a struct
23+
A(u32), // Single primitive value
24+
B { x: u8, y: i16, z: u8 }, // Composite, and the offsets of `y` and `z`
25+
// depend on tag being internal
26+
C, // Empty
27+
D(Option<u32>), // Contains an enum
28+
E(Duration), // Contains a struct
2829
}
2930

3031
#[repr(C)]
@@ -44,14 +45,14 @@ union MyEnumPayload {
4445

4546
#[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E }
4647
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32);
47-
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 }
48+
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 }
4849
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option<u32>);
4950
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration);
5051

5152
fn main() {
5253
let result: Vec<Result<MyEnum, ()>> = vec![
5354
Ok(MyEnum::A(17)),
54-
Ok(MyEnum::B { x: 206, y: 1145 }),
55+
Ok(MyEnum::B { x: 206, y: 1145, z: 78 }),
5556
Ok(MyEnum::C),
5657
Err(()),
5758
Ok(MyEnum::D(Some(407))),
@@ -63,7 +64,7 @@ fn main() {
6364
// Binary serialized version of the above (little-endian)
6465
let input: Vec<u8> = vec![
6566
0, 17, 0, 0, 0,
66-
1, 206, 121, 4,
67+
1, 206, 121, 4, 78,
6768
2,
6869
8, /* invalid tag value */
6970
3, 0, 151, 1, 0, 0,
@@ -112,6 +113,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> {
112113
MyEnumTag::B => {
113114
dest.payload.B.x = read_u8(buf)?;
114115
dest.payload.B.y = read_u16_le(buf)? as i16;
116+
dest.payload.B.z = read_u8(buf)?;
115117
}
116118
MyEnumTag::C => {
117119
/* do nothing */

src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ use std::mem;
2020
#[repr(C)]
2121
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
2222
enum MyEnum {
23-
A(u32), // Single primitive value
24-
B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal
25-
C, // Empty
26-
D(Option<u32>), // Contains an enum
27-
E(Duration), // Contains a struct
23+
A(u32), // Single primitive value
24+
B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z`
25+
// depend on tag being internal
26+
C, // Empty
27+
D(Option<u32>), // Contains an enum
28+
E(Duration), // Contains a struct
2829
}
2930

3031
#[repr(C)]
@@ -44,14 +45,14 @@ union MyEnumPayload {
4445

4546
#[repr(C)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E }
4647
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32);
47-
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 }
48+
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 }
4849
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option<u32>);
4950
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration);
5051

5152
fn main() {
5253
let result: Vec<Result<MyEnum, ()>> = vec![
5354
Ok(MyEnum::A(17)),
54-
Ok(MyEnum::B { x: 206, y: 1145 }),
55+
Ok(MyEnum::B { x: 206, y: 1145, z: 78 }),
5556
Ok(MyEnum::C),
5657
Err(()),
5758
Ok(MyEnum::D(Some(407))),
@@ -63,7 +64,7 @@ fn main() {
6364
// Binary serialized version of the above (little-endian)
6465
let input: Vec<u8> = vec![
6566
0, 17, 0, 0, 0,
66-
1, 206, 121, 4,
67+
1, 206, 121, 4, 78,
6768
2,
6869
8, /* invalid tag value */
6970
3, 0, 151, 1, 0, 0,
@@ -112,6 +113,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> {
112113
MyEnumTag::B => {
113114
dest.payload.B.x = read_u8(buf)?;
114115
dest.payload.B.y = read_u16_le(buf)? as i16;
116+
dest.payload.B.z = read_u8(buf)?;
115117
}
116118
MyEnumTag::C => {
117119
/* do nothing */

src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ use std::mem;
2020
#[repr(u8)]
2121
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
2222
enum MyEnum {
23-
A(u32), // Single primitive value
24-
B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal
25-
C, // Empty
26-
D(Option<u32>), // Contains an enum
27-
E(Duration), // Contains a struct
23+
A(u32), // Single primitive value
24+
B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z`
25+
// depend on tag being internal
26+
C, // Empty
27+
D(Option<u32>), // Contains an enum
28+
E(Duration), // Contains a struct
2829
}
2930

3031
#[allow(non_snake_case)]
@@ -39,15 +40,15 @@ union MyEnumRepr {
3940

4041
#[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E }
4142
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(MyEnumTag, u32);
42-
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16 }
43+
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16, z: u8 }
4344
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantC(MyEnumTag);
4445
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(MyEnumTag, Option<u32>);
4546
#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(MyEnumTag, Duration);
4647

4748
fn main() {
4849
let result: Vec<Result<MyEnum, ()>> = vec![
4950
Ok(MyEnum::A(17)),
50-
Ok(MyEnum::B { x: 206, y: 1145 }),
51+
Ok(MyEnum::B { x: 206, y: 1145, z: 78 }),
5152
Ok(MyEnum::C),
5253
Err(()),
5354
Ok(MyEnum::D(Some(407))),
@@ -59,7 +60,7 @@ fn main() {
5960
// Binary serialized version of the above (little-endian)
6061
let input: Vec<u8> = vec![
6162
0, 17, 0, 0, 0,
62-
1, 206, 121, 4,
63+
1, 206, 121, 4, 78,
6364
2,
6465
8, /* invalid tag value */
6566
3, 0, 151, 1, 0, 0,
@@ -108,6 +109,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> {
108109
MyEnumTag::B => {
109110
dest.B.x = read_u8(buf)?;
110111
dest.B.y = read_u16_le(buf)? as i16;
112+
dest.B.z = read_u8(buf)?;
111113
}
112114
MyEnumTag::C => {
113115
/* do nothing */

0 commit comments

Comments
 (0)