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

Static Dispatch and Inlining

Influence compiler inlining decisions to optimize generic function calls.

In this lesson, you will learn how the Rust compiler uses inlining to transform generic functions into high-performance, specialized machine code.

When you use generics with trait bounds, Rust performs static dispatch. This means that at compile time, the compiler knows exactly which concrete type is being used and replaces the generic function with a version specific to that type (a process called monomorphization). However, even after this step, there is still the overhead of a function call—pushing arguments onto the stack and jumping to a new memory address.

This is where inlining comes in. Inlining is an optimization where the compiler takes the body of a function and "pastes" it directly into the caller's code. By eliminating the function call entirely, the compiler can often perform further optimizations, such as constant folding or dead code elimination, across the boundaries of the original function.

Consider this generic function:

trait Calculator {
    fn add(&self, a: i32, b: i32) -> i32;
}

// Hinting to the compiler to inline this
#[inline]
fn compute<T: Calculator>(calc: T, x: i32, y: i32) -> i32 {
    calc.add(x, y)
}

By adding the #[inline] attribute, you are providing a strong hint to the compiler that the cost of the function call outweighs the benefit of keeping the function separate. When combined with static dispatch, the compiler effectively replaces the compute call with the actual logic inside add, resulting in code that is often as fast as if you had written the logic manually for a specific type.

However, use this power carefully. If you force the compiler to inline a very large function, you can increase your binary size (the "code bloat" mentioned in earlier lessons), which can actually hurt performance by reducing CPU cache efficiency. Rust's compiler is already very smart at heuristic-based inlining, so #[inline] is best reserved for small, frequently called generic functions where you want to ensure the performance overhead of the abstraction vanishes completely.

Key Takeaway: Static dispatch allows the compiler to know the exact code to execute, while the #[inline] attribute enables the removal of function call overhead, pushing your code toward the theoretical limit of execution speed.