tezvyn:

Zero-Cost Abstractions: Pay at Compile Time, Not Runtime

AI-drafted, machine-checkedSource: doc.rust-lang.orgadvanced

Zero-cost abstractions let you write high-level code that compiles to the same machine code as low-level optimizations. This is key in Rust for safe APIs without runtime overhead.

WHY IT EXISTS High-level code is safer and easier to reason about, but low-level code is often faster. Zero-cost abstractions were created to eliminate this trade-off, allowing developers to write expressive, safe code that performs as well as hand-optimized, low-level equivalents.

THE MENTAL MODEL Think of a zero-cost abstraction as a blueprint for a building. The blueprint (the abstraction) is incredibly detailed, ensuring every part fits together correctly during construction (compile time). Once the building is complete (the program is compiled), the blueprint is thrown away. The final structure is simple and efficient, with no trace of the complex plans that made it possible.

HOW IT WORKS The primary mechanism in Rust is the use of Zero-Sized Types (ZSTs). A ZST is a type that contains no data and occupies zero bytes of memory at runtime, like struct Enabled;. These types exist only for the compiler's type checker. They act as markers or states. The compiler enforces rules based on these types, and then the optimizer sees they hold no data and completely erases them and any logic that just moves them around. The code boils down to the essential machine instructions.

WHEN TO USE IT This pattern is ideal for building safe APIs over unsafe foundations, such as raw hardware registers or memory manipulation. Rust's iterators are a classic example; they provide a rich, functional API but compile down to loops that are just as fast as a manual C-style loop. In embedded systems, it's used for type-state programming to create compile-time state machines, making invalid hardware operations a compile error.

WHEN NOT TO USE IT The "zero-cost" label is not a blanket promise. An abstraction is not zero-cost if it requires runtime information, such as dynamic dispatch using trait objects. The principle only applies when the compiler has all information needed at compile time to prove the abstraction away. Do not assume an abstraction is zero-cost without understanding its implementation; if it allocates or uses vtables, it has a cost.

ONE CANONICAL EXAMPLE In embedded Rust, a GPIO pin can be represented by a struct like GpioConfig<Enabled, Input>. The types Enabled and Input are ZSTs that enforce the pin's state. A function to read from the pin would only be defined for this specific type. When you call it, the compiler checks the types, confirms the operation is valid, and then generates a single assembly instruction to read a hardware register. The GpioConfig struct and its ZSTs never exist in the final running code.

Read the original → doc.rust-lang.org

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.