Keyword union

source ·
Expand description

The Rust equivalent of a C-style union.

A union looks like a struct in terms of declaration, but all of its fields exist in the same memory, superimposed over one another. For instance, if we wanted some bits in memory that we sometimes interpret as a u32 and sometimes as an f32, we could write:

union IntOrFloat {
    i: u32,
    f: f32,
}

let mut u = IntOrFloat { f: 1.0 };
// Reading the fields of a union is always unsafe
assert_eq!(unsafe { u.i }, 1065353216);
// Updating through any of the field will modify all of them
u.i = 1073741824;
assert_eq!(unsafe { u.f }, 2.0);
Run

Matching on unions

It is possible to use pattern matching on unions. A single field name must be used and it must match the name of one of the union’s field. Like reading from a union, pattern matching on a union requires unsafe.

union IntOrFloat {
    i: u32,
    f: f32,
}

let u = IntOrFloat { f: 1.0 };

unsafe {
    match u {
        IntOrFloat { i: 10 } => println!("Found exactly ten!"),
        // Matching the field `f` provides an `f32`.
        IntOrFloat { f } => println!("Found f = {f} !"),
    }
}
Run

References to union fields

All fields in a union are all at the same place in memory which means borrowing one borrows the entire union, for the same lifetime:

union IntOrFloat {
    i: u32,
    f: f32,
}

let mut u = IntOrFloat { f: 1.0 };

let f = unsafe { &u.f };
// This will not compile because the field has already been borrowed, even
// if only immutably
let i = unsafe { &mut u.i };

*i = 10;
println!("f = {f} and i = {i}");
Run

See the Reference for more information on unions.