-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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 reftest that checks the layout of repr(int) on non-c-like enums #45688
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
@bors: r+ Nice! |
📌 Commit 95a7f29 has been approved by |
Add reftest that checks the layout of repr(int) on non-c-like enums This verifies the first layout specified in rust-lang/rfcs#2195 The second (`repr(C)`) layout isn't included here because it doesn't actually exist today. However if/when that's implemented a second test could be fairly easily derived from this one. CC @eddyb
💔 Test failed - status-travis |
The diff: --- 1.txt 2017-11-03 15:20:03.000000000 +0800
+++ 2.txt 2017-11-03 15:20:16.000000000 +0800
@@ -75,8 +75,10 @@
[01:22:58] let input: Vec<u8> =
[01:22:58] vec!(0 , 17 , 0 , 0 , 0 , 1 , 206 , 121 , 4 , 2 , 8 , 3 , 0 , 151 , 1
[01:22:58] , 0 , 0 , 3 , 1 , 4 , 100 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
-[01:22:58] , 0 , 0 ,); // Invalid tag value
-[01:22:58] // Incomplete value
+[01:22:58] , 0 , 0
+[01:22:58] ,); // Invalid tag value
+[01:22:58] // Incomplete value
+[01:22:58]
[01:22:58]
[01:22:58] let mut output = vec!();
[01:22:58] let mut buf = &input[..]; (1.txt is "expected", 2.txt is "actual") You could run this test with ./x.py test src/test/run-pass/pretty --test-args enum-non-c-like-repr-int |
} | ||
|
||
fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { | ||
unsafe { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be worth to limit this unsafe
block only to transmute
instruction? (doesn't look like anything else in the function needs it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All union accesses are unsafe, afaik
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gankro Writing to a union doesn't require unsafe block, only reading does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I read the union at the start of the match, and if we're being honest, writing to the unions is Pretty Unsafe. It's just not unsafe
for rules-lawyer reasons.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gankro Writing to unions just puts contents into Schrodinger's state - they might or might be not corrupt until you try to read them 😄
This verifies the layout specified in rfc rust-lang#2195
Tidy fixed. |
@bors r=alexcrichton |
📌 Commit e156f89 has been approved by |
Add reftest that checks the layout of repr(int) on non-c-like enums This verifies the first layout specified in rust-lang/rfcs#2195 The second (`repr(C)`) layout isn't included here because it doesn't actually exist today. However if/when that's implemented a second test could be fairly easily derived from this one. CC @eddyb
☀️ Test successful - status-appveyor, status-travis |
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.
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.
This verifies the first layout specified in rust-lang/rfcs#2195
The second (
repr(C)
) layout isn't included here because it doesn't actually exist today. However if/when that's implemented a second test could be fairly easily derived from this one.CC @eddyb