union for an unsafe form of enum
Rust now supports unions
:
#![allow(unused_variables)]
fn main() {
union MyUnion {
f1: u32,
f2: f32,
}
}
Unions are kind of like enums, but they are “untagged”. Enums have a “tag”that stores which variant is the correct one at runtime; unions don't havethis tag.
Since we can interpret the data held in the union using the wrong variant andRust can’t check this for us, that means reading a union’s field is unsafe:
#![allow(unused_variables)]
fn main() {
union MyUnion {
f1: u32,
f2: f32,
}
let mut u = MyUnion { f1: 1 };
u.f1 = 5;
let value = unsafe { u.f1 };
}
Pattern matching works too:
#![allow(unused_variables)]
fn main() {
union MyUnion {
f1: u32,
f2: f32,
}
fn f(u: MyUnion) {
unsafe {
match u {
MyUnion { f1: 10 } => { println!("ten"); }
MyUnion { f2 } => { println!("{}", f2); }
}
}
}
}
When are unions useful? One major use-case is interoperability with C. C APIscan (and depending on the area, often do) expose unions, and so this makeswriting API wrappers for those libraries significantly easier. Additionally,unions also simplify Rust implementations of space-efficient orcache-efficient structures relying on value representation, such asmachine-word-sized unions using the least-significant bits of alignedpointers to distinguish cases.
There’s still more improvements to come. For now, unions can only includeCopy
types and may not implement Drop
. We expect to lift theserestrictions in the future.