Course contentsShow
← Rust
Lesson 689 of 1,9106. Generics and Static DispatchFree lesson

Data Layout and Alignment with Generics

Ensure generic structs maintain predictable memory alignment across different instantiations.

In this lesson, you will learn how the Rust compiler determines memory layout for generic structs and how your type choices impact alignment.

How Rust Packs Generic Memory

When you define a struct with a generic parameter, like struct Container<T> { data: T }, Rust does not know the final size or alignment of T until you actually instantiate it. Because of monomorphization, the compiler creates a specific version of Container<T> for every concrete type you use.

The compiler follows a simple rule: a struct's alignment is determined by its most strictly aligned field. When that field is a generic type T, the alignment of your struct depends entirely on what T is.

The Alignment Challenge

Consider this example:

struct Wrapper<T> {
    flag: u8,
    value: T,
}

If you use Wrapper<u8>, the size is 2 bytes (1 byte for flag, 1 byte for u8, no padding needed). However, if you use Wrapper<u64>, the compiler must insert 7 bytes of padding after flag to ensure the u64 starts on an 8-byte boundary.

This means the memory layout of Wrapper<T> is dynamic. While this is efficient—it prevents the "bloat" of forcing every instance to align to the size of the largest possible type—it creates a pitfall: you cannot predict the exact memory offset of your fields if you don't know the concrete type of T.

Why Does This Matter?

If you are building low-level systems or working with FFI (Foreign Function Interface), assuming a fixed layout for generic structs will lead to bugs. Rust does not guarantee a specific field order or padding for standard structs unless you explicitly use the #[repr(C)] attribute. Even with #[repr(C)], the alignment of your struct remains dependent on the alignment of the generic type T. If you swap T for a type with a higher alignment requirement, your entire struct will automatically increase its padding to accommodate it.

Key Takeaway: Because Rust monomorphizes generics, the alignment and size of a generic struct are determined at compile-time based on the concrete type, meaning your struct’s memory footprint shifts to match the requirements of the type parameter provided.