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)

  1. ALWAYS use impl Trait when the function returns or accepts ONE concrete type per call site. NEVER use dyn Trait just to "be flexible"; monomorphization costs binary size but is faster at the call site.
  2. ALWAYS use dyn Trait when 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.
  3. ALWAYS prefer &dyn Trait over Box<dyn Trait> when ownership transfer is not required. Box<dyn Trait> allocates on the heap; &dyn Trait is two stack words (data pointer + vtable pointer).
  4. 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).
  5. NEVER include where Self: Sized on a method you want dispatched through the vtable; that bound opts the method out of the vtable, making it callable only on concrete types.
  6. ALWAYS exploit trait upcasting (&dyn Sub to &dyn Super) directly in Rust 1.86+ . NEVER write an as_supertrait() workaround method; it was the pre-1.86 workaround and is now obsolete.
  7. 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 allow use<> in trait positions.

Decision tree: dyn Trait vs impl Trait

Installs
2
GitHub Stars
1
First Seen
May 24, 2026