-
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
Variant with value 1 of binary field-less enum with repr(i8) is transmuted to -1 #51582
Comments
Why is this a bug? I didn't think that either |
Because the binary representation of let b = unsafe { std::mem::transmute::<i8, Enum>(std::mem::transmute::<Enum, i8>(Enum::VariantB)) };
assert_eq!(1, Enum::VariantB as i8);
assert_eq!(1, b as i8); The first assertion passes, the second assertion fails with:
Further, if we derive Debug and PartialEq for assert_eq!(Enum::VariantB, b);
println!("{:?}", b); the first line passes, the second fails with
(Btw. I don't have previous code. I just try to write serialization for such enums. And logically, since this is not working, we (on IRC) checked for which compilers it worked before.) |
This is a pre-miri compiler. Can you try the current stable and nightly? Also I agree with @shepmaster , the memory representation of the enum could just as well be 42 and 99 for the variants, even if casting results in the discriminant values 0 and 1. Maybe repr(I8) has a defined layout, you should check the RFC. |
The failing checks and illegal instruction for the current stable 1.26.2 (594fb25 2018-06-01) and latest nightly 1.28.0-nightly (967c1f3 2018-06-15) are still present. In the extended test, I do not assume anything about the memory representation except that it should be unique. This does not hold. More severely, println terminates the program with illegal hardware instruction. I am not sure what In the assembly code (https://godbolt.org/g/WuCRLG) generated for About the RFC: I cannot find in which RFC |
@shepmaster @oli-obk What you're saying holds for an enum with explicit discriminant values, but without Looking at this formulation (on playground): pub fn roundtrip(x: i8) -> i8 {
(unsafe { std::mem::transmute::<i8, Enum>(x) }) as i8
} %3 = trunc i8 %2 to i1
; ...
%5 = sext i1 %3 to i8
ret i8 %5 So that seems wrong. Because the What I don't understand is why this would work in 1.23.0, if the bug was introduced in f62e43d. |
Note that you don't even need transmute, it's the #[repr(i8)]
pub enum Enum {
VariantA,
VariantB,
}
fn make_b() -> Enum { Enum::VariantB }
fn main() {
assert_eq!(1, make_b() as i8);
} Also, it doesn't matter what type is being cast to, neither the size nor the signedness, it's always |
@rust-lang/compiler Do we want to backport the fix for this? |
The fix was simple enough and fixes a fairly serious problem so I'd prefer
to backport.
S.
…On Sun, Jun 17, 2018, 09:14 Eduard-Mihai Burtescu ***@***.***> wrote:
@rust-lang/compiler <https://github.com/orgs/rust-lang/teams/compiler> Do
we want to backport the fix for this?
—
You are receiving this because you are on a team that was mentioned.
Reply to this email directly, view it on GitHub
<#51582 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AApc0j8j4yF6C-1ev4-ntSspEyqoTOJwks5t9fPigaJpZM4UqOar>
.
|
This code reproduces the bug:
Output:
in debug and release modes starting with compiler:
The test passes for:
Not affected are enums with more than 2 values, and enums with
repr({i16, i32, i64})
.The text was updated successfully, but these errors were encountered: