-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add (failing) test to check order of repr(int) enum fields #56619
Add (failing) test to check order of repr(int) enum fields #56619
Conversation
RFC rust-lang#2195 specifies that a repr(int) enum such as: #[repr(u8)] enum MyEnum { B { x: u8, y: i16, z: u8 }, } has a layout that is equivalent to: #[repr(C)] enum MyEnumVariantB { tag: u8, x: u8, y: i16, z: u8 }, However this isn't actually implemented, with the actual layout being roughly equivalent to: union MyEnumPayload { B { x: u8, y: i16, z: u8 }, } #[repr(packed)] struct MyEnum { tag: u8, payload: MyEnumPayload, } Thus the variant payload is *not* subject to repr(C) ordering rules, and gets re-ordered as `{ x: u8, z: u8, z: i16 }` The existing tests added in pull-req rust-lang#45688 fail to catch this as the repr(C) ordering just happens to match the current Rust ordering in this case; adding a third field reveals the problem.
(rust_highfive has picked a reviewer for you, use r? to override) |
...as for how to actually fix this, that's above my pay-grade for now. :) |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
r? @eddyb |
Note: looks like the tests added in #50354 also have this flaw. edit: Also https://gist.github.com/Gankro/5223984900f2e2536fc4676fd8150653 |
I think a patch like this should fix it, though haven't tested it: diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index a1fc949137..227b75a772 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2061,7 +2061,8 @@ impl ReprOptions {
/// Returns `true` if this `#[repr()]` should inhibit struct field reordering
/// optimizations, such as with repr(C) or repr(packed(1)).
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 |
I just confirmed that fixes the test, will submit a PR with that and your test. |
Opened #56887 (kept you as the author of the test of course :)) |
/cc @gankro |
oops, yep, nice catch! |
Disable field reordering for repr(int). This fixes the problem that the test in rust-lang#56619 uncovers. Closes rust-lang#56619.
Disable field reordering for repr(int). This fixes the problem that the test in rust-lang#56619 uncovers. Closes rust-lang#56619.
Disable field reordering for repr(int). This fixes the problem that the test in rust-lang#56619 uncovers. Closes rust-lang#56619.
Disable field reordering for repr(int). This fixes the problem that the test in rust-lang#56619 uncovers. Closes rust-lang#56619.
RFC #2195 specifies that a repr(int) enum such as:
has a layout that is equivalent to:
However this isn't actually implemented, with the actual layout being roughly equivalent to:
Thus the variant payload is not subject to repr(C) ordering rules, and gets re-ordered as
{ x: u8, z: u8, z: i16 }
The existing tests added in pull-req #45688 fail to catch this as the repr(C) ordering just happens to match the current Rust ordering in this case; adding a third field reveals the problem.