Course contentsShow
← Rust
Lesson 592 of 1,9105. Type System and TraitsFree lesson

The role of the Sized bound in performance

Optimize for stack allocation by keeping types Sized where possible.

In this lesson, you will learn how the Sized trait bound enables the Rust compiler to generate high-performance machine code by placing data directly on the stack.

Why Size Matters

In Rust, the compiler needs to know exactly how many bytes a type occupies to allocate space for it on the stack. A type is Sized if its size is known at compile time. By default, almost every type you use (like i32, struct, or [f64; 3]) is Sized.

When a type is Sized, the compiler can calculate the precise memory offset for variables, enabling extremely fast access. If we lose that guarantee—such as when using trait objects like dyn Trait—we enter the realm of "unsized" types. These cannot live on the stack because the compiler doesn't know how much room to reserve, forcing us to use indirection like pointers (&dyn Trait or Box<dyn Trait>).

The Performance Cost

Consider a generic function:

fn process<T>(item: T) {
    // T is implicitly T: Sized
}

Because T is Sized, the compiler generates a specialized version of this function where the size is fixed. It knows exactly where item lives in memory. If we explicitly opt out of this requirement using ?Sized:

fn process_unsized<T: ?Sized>(item: &T) {
    // We can no longer pass the value directly, 
    // only a reference (pointer) to it.
}

When we work with ?Sized types, the compiler loses the ability to perform certain optimizations, such as inlining the data directly into the caller's stack frame. It must treat the data as a "fat pointer," which includes an extra pointer to a vtable (dynamic dispatch), adding a small but measurable overhead to every access.

Keep it Sized

By default, you are always using Sized. You only move away from it when you have a specific architectural need for polymorphism via trait objects. By keeping your types Sized whenever possible, you allow the compiler to pack data tightly in memory, avoid unnecessary pointer dereferencing, and perform aggressive code optimization.

Key Takeaway: Keeping types Sized allows the compiler to allocate memory on the stack and optimize data access, whereas opting out (?Sized) forces heap allocation or pointer indirection, which carries a performance cost.