> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust Union

A union in Rust is a user-defined composite type where all declared fields share the same underlying memory allocation. The size of a union is determined by its largest field, plus any necessary padding required to satisfy alignment constraints. Because the compiler cannot track which field (or "variant") was last written to, reading from a union bypasses Rust's standard type safety guarantees and is an inherently `unsafe` operation.

## Declaration

Unions are declared using the `union` keyword, followed by a set of named and typed fields. The syntax is identical to that of a standard C-style struct.

```rust theme={"dark"}
union IntOrFloat {
    i: u32,
    f: f32,
}
```

## Instantiation

To instantiate a union, you must specify exactly one field to initialize. This establishes the initial bit pattern in the shared memory space.

```rust theme={"dark"}
let mut u = IntOrFloat { f: 3.14 };
```

## Memory Layout

Unlike an `enum` (which includes a hidden discriminant tag to track the active variant at runtime), a `union` contains no metadata.

If a union contains a `u8` (1 byte) and a `u64` (8 bytes), the total size of the union will be 8 bytes, aligned to the 8-byte boundary. Writing to the `u8` field will only overwrite the first byte of the 8-byte allocation, leaving the remaining 7 bytes in an indeterminate state based on whatever was previously stored there.

## Field Access and Safety

Writing to a union field is generally safe, as it merely overwrites the bits in the shared memory location. However, reading from a union field requires an `unsafe` block. The compiler relies entirely on the developer to ensure that the memory is being interpreted as the correct type.

```rust theme={"dark"}
let mut u = IntOrFloat { i: 42 };

// Writing is safe
u.f = 2.718;

// Reading is unsafe; the programmer asserts the memory contains a valid f32
let float_val = unsafe { u.f };
```

Interpreting the memory as the wrong type (e.g., reading the `f32` field when a `u32` was written) does not cause a compilation error. Instead, it results in a bit-cast, which may produce garbage data or trigger undefined behavior if the bit pattern is invalid for the target type (such as an invalid `bool` or `char`).

## Pattern Matching

You can use pattern matching to extract values from a union. A union pattern can only specify exactly one field per pattern. Because matching on a union field is equivalent to reading it, the destructuring must occur within an `unsafe` block.

Rust strictly enforces that **union patterns must be irrefutable**. You cannot use a refutable pattern to match a specific value directly in the union pattern (e.g., `IntOrFloat { i: 42 }` will be rejected by the compiler). Instead, you must bind the field to a variable.

While you can create a multi-arm `match` statement using match guards, this introduces significant risk. Because union patterns are irrefutable, multi-arm matches are only possible if the preceding arms use guards (e.g., `IntOrFloat { i } if i == 0 => ...`). Match guards evaluate sequentially, meaning a guard will read the field's memory to evaluate the condition. If the underlying bit pattern is invalid for the type being evaluated in the guard, this sequential read will trigger undefined behavior before the correct arm is ever reached.

```rust theme={"dark"}
let u = IntOrFloat { i: 42 };

unsafe {
    // Destructuring a single field using an irrefutable let binding
    let IntOrFloat { i } = u;
    println!("Integer value: {}", i);
    
    // Single-arm match with an irrefutable pattern
    match u {
        IntOrFloat { i: matched_val } => println!("Matched: {}", matched_val),
    }
}
```

## Drop Behavior and Non-Copy Types

By default, unions work seamlessly with types that implement the `Copy` trait. Because the compiler does not know which field is currently active, it cannot safely determine which destructor to run when the union goes out of scope.

To prevent undefined behavior during destruction, Rust requires that **any non-`Copy` type** (regardless of whether it explicitly implements `Drop` or not) must be wrapped in `std::mem::ManuallyDrop<T>` to be placed in a union. This explicitly disables automatic cleanup, forcing the developer to manually drop the inner value using `unsafe` code before the union is destroyed.

```rust theme={"dark"}
use std::mem::ManuallyDrop;

union StringOrInt {
    s: ManuallyDrop<String>,
    i: i32,
}

let mut u = StringOrInt { 
    s: ManuallyDrop::new(String::from("Hello")) 
};

// The developer is strictly responsible for dropping the allocated memory
unsafe {
    ManuallyDrop::drop(&mut u.s);
}
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor Rust Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
