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

The Philosophy of Monomorphization

Explain how the Rust compiler generates machine code for each concrete type used in a generic function.

In this lesson, you will learn how Rust turns generic blueprints into lightning-fast machine code through a process called monomorphization.

When you define a function using a generic type, such as fn display<T: Display>(item: T), you aren't writing code that runs directly. Instead, you are providing the compiler with a template. The compiler cannot generate machine code for this function immediately because it doesn’t know what size or behavior T will have at runtime.

The Transformation

"Monomorphization" literally means "turning into one form." When you call display(10) (an i32) and display("Hello") (a &str) in your program, the Rust compiler performs a "search and replace" operation. It duplicates your generic function for every concrete type you use.

Imagine your code looks like this:

fn print_item<T: std::fmt::Display>(item: T) {
    println!("{}", item);
}

fn main() {
    print_item(5);       // Compiler generates print_item_i32
    print_item("Rust");  // Compiler generates print_item_str
}

Behind the scenes, the compiler creates two distinct versions of the function, effectively rewriting your code into:

fn print_item_i32(item: i32) { println!("{}", item); }
fn print_item_str(item: &str) { println!("{}", item); }

The Performance Trade-off

Because the compiler creates specialized machine code for every type, it knows exactly how to handle that type. It doesn't need to look up function pointers or perform dynamic checks at runtime. The CPU can inline these functions and optimize them heavily because the types are locked in at compile time.

However, there is a small cost: this is why Rust programs can take longer to compile, and why your binary size increases as you use more generic types—every unique type you plug into a generic function results in a new block of machine code. It is a classic "space-for-time" trade-off, where we sacrifice a bit of compilation speed and binary size to achieve maximum execution performance.

Key Takeaway: Monomorphization is the compiler’s way of ensuring that generic abstractions vanish at runtime by creating specialized, optimized machine code for every unique type you provide.