Rust's dyn Trait: How Vtables Work In Memory
Original: Visualizing Rust's Vtables: How dyn Trait Works In Memory
Why This Matters
Deep systems-level understanding of Rust's dispatch model is increasingly critical as Rust adoption grows in systems and safety-critical software.
Engineer Sofía Belén López Vicens published a detailed technical breakdown of Rust's vtable mechanism, comparing dynamic dispatch via dyn Trait with C++ virtual functions and CRTP, and examining object safety constraints and zero-sized types.
The article, authored by Sofía Belén López Vicens, provides an in-depth exploration of how Rust implements polymorphism through dyn Trait and vtables. The author begins by framing the core problem: calling draw() on a heterogeneous collection of shapes (Circle, Square, Triangle), then compares three approaches across C++ and Rust.
In C++, virtual functions embed a vtable pointer inside each object, enabling automatic runtime dispatch. An alternative, CRTP (Curiously Recurring Template Pattern), achieves compile-time polymorphism at the cost of readability. Rust's analog to CRTP is monomorphization via generics (static dispatch), where the compiler generates a separate function copy per type with zero runtime overhead.
For dynamic dispatch, Rust uses dyn Trait. Unlike C++, where the vtable pointer lives inside the object, Rust stores it externally in a fat pointer — a two-word structure containing a data pointer and a vtable pointer. Each unique (Type, Trait) pair generates exactly one vtable.
The article also covers object safety rules that restrict which traits can be used with dyn: methods must not return Self, and methods must not have generic type parameters. The author emphasizes that understanding Rust through C++ analogies has limits, as the two languages have fundamentally different design philosophies. All code and experiments are available on GitHub.