The official rust documentation guarantees the layout of a repr(C, u8)
enum (with fields), in terms of an equivalent set of types implementing a manually tagged union. If I define both implementations, am I justified in interconverting between the two with mem::transmute?
The motivation is that in most of my code I want to use a nice ergonomic rust enum, but in one or two places I need to do unsafe operations on the tagged union representation.
/// BEGIN copy-paste from
/// https://doc.rust-lang.org/reference/type-layout.html#combining-primitive-representations-of-enums-with-fields-and-reprc
// This Enum has the same representation as ...
#[repr(C, u8)]
enum MyEnum {
A(u32),
B(f32, u64),
C { x: u32, y: u8 },
D,
}
// ... this struct.
#[repr(C)]
struct MyEnumRepr {
tag: MyEnumDiscriminant,
payload: MyEnumFields,
}
// This is the discriminant enum.
#[repr(u8)]
enum MyEnumDiscriminant { A, B, C, D }
// This is the variant union.
#[repr(C)]
union MyEnumFields {
A: MyAFields,
B: MyBFields,
C: MyCFields,
D: MyDFields,
}
#[repr(C)]
#[derive(Copy, Clone)]
struct MyAFields(u32);
#[repr(C)]
#[derive(Copy, Clone)]
struct MyBFields(f32, u64);
#[repr(C)]
#[derive(Copy, Clone)]
struct MyCFields { x: u32, y: u8 }
// This struct could be omitted (it is a zero-sized type), and it must be in
// C/C++ headers.
#[repr(C)]
#[derive(Copy, Clone)]
struct MyDFields;
/// END copy-paste
fn as_tagged_union(x: &mut MyEnum) -> &mut MyEnumRepr {
unsafe { core::mem::transmute(x) }
}
fn as_enum(x: &mut MyEnumRepr) -> &mut MyEnum {
unsafe { core::mem::transmute(x) }
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=265f2e01773acb17fa199360c62fb56e