rust-syntax-trait-objects
Installation
SKILL.md
rust-syntax-trait-objects
Trait objects (dyn Trait) provide runtime polymorphism through type erasure and a vtable. They are the dynamic-dispatch counterpart to impl Trait (static dispatch via monomorphization). This skill covers the vtable layout, the dyn-compatibility rules formerly known as object safety, the decision between dyn and impl, trait upcasting stabilized in 1.86, and precise capturing inside trait definitions stabilized in 1.87.
Quick Reference
Core rules (deterministic)
- ALWAYS use
impl Traitwhen the function returns or accepts ONE concrete type per call site. NEVER usedyn Traitjust to "be flexible"; monomorphization costs binary size but is faster at the call site. - ALWAYS use
dyn Traitwhen storing heterogeneous values in a single collection (Vec<Box<dyn Drawable>>) or when a function must accept values of different concrete types at the same call site. - ALWAYS prefer
&dyn TraitoverBox<dyn Trait>when ownership transfer is not required.Box<dyn Trait>allocates on the heap;&dyn Traitis two stack words (data pointer + vtable pointer). - NEVER add a generic method to a trait that must remain dyn-compatible. A generic method requires a separate vtable entry per instantiation; the vtable has fixed shape, so the compiler rejects it (E0038).
- NEVER include
where Self: Sizedon a method you want dispatched through the vtable; that bound opts the method out of the vtable, making it callable only on concrete types. - ALWAYS exploit trait upcasting (
&dyn Subto&dyn Super) directly in Rust 1.86+ . NEVER write anas_supertrait()workaround method; it was the pre-1.86 workaround and is now obsolete. - ALWAYS add
+ use<'a, T>to an RPIT inside a trait definition in Rust 1.87+ when you need to constrain or exclude captured generics. NEVER rely on pre-1.87 syntax that did not allowuse<>in trait positions.