Skip to main content

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.

A unit struct is a struct defined without any fields, terminating with a semicolon instead of curly braces. In Rust’s type system, it is classified as a Zero-Sized Type (ZST). Because it contains no data, the struct itself occupies exactly zero bytes of memory at runtime, and the compiler optimizes away any runtime overhead associated with its instantiation, copying, or moving.

Syntax and Instantiation

A unit struct is defined using the struct keyword followed by the identifier and a semicolon. It is instantiated using only its identifier, without parentheses or curly braces.
// Definition
struct UnitStruct;

fn main() {
    // Instantiation
    let instance = UnitStruct;
}

Memory Characteristics

Because a unit struct lacks fields, the Rust compiler does not allocate memory for the value itself. You can verify this using std::mem::size_of.
use std::mem;

struct UnitStruct;

fn main() {
    assert_eq!(mem::size_of::<UnitStruct>(), 0);
}
When a unit struct is passed to a function or returned by value, no actual data is copied or moved at the machine-code level. The type exists purely at compile time for type checking and dispatch.

Method and Trait Implementation

Despite having no internal state, unit structs are fully qualified types. You can implement inherent methods and traits for them using standard impl blocks.
struct UnitStruct;

// Inherent methods
impl UnitStruct {
    fn execute(&self) {
        println!("Executing method on a ZST.");
    }
}

// Trait implementation
trait Processor {
    fn process(&self);
}

impl Processor for UnitStruct {
    fn process(&self) {
        println!("Processing via trait.");
    }
}
When methods are called on a unit struct, the self parameter is passed as a zero-sized value. If the method takes a reference (&self), the reference itself is a standard pointer and occupies pointer-sized memory (e.g., 8 bytes on a 64-bit architecture), but it points to a zero-sized value. Regardless of how it is passed, the compiler resolves the method call statically without needing to dereference a memory address to read internal state.

Pattern Matching and Destructuring

Unit structs can be matched in match expressions. Because they have only one possible value (the unit itself), matching against them is exhaustive by default.
struct UnitStruct;

fn evaluate(val: UnitStruct) {
    match val {
        UnitStruct => println!("Matched the unit struct exactly."),
    }
}

Deriving Traits

Unit structs support the #[derive(...)] attribute. Standard library traits like Debug, Clone, Copy, PartialEq, and Eq can be automatically derived. Because there are no fields to compare or copy, these derived implementations are trivial and incur zero runtime cost.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct UnitStruct;

fn main() {
    let a = UnitStruct;
    let b = a; // Implicitly copied due to `Copy`
    
    assert_eq!(a, b); // Evaluates to true via `PartialEq`
}
Master Rust with Deep Grasping Methodology!Learn More