A trait object lets Rust use values of different concrete types through one shared trait interface. Method calls use dynamic dispatch: the method to run is selected at runtime. This is useful when a collection must hold different types, or a function must return different error types. section 8.3.1 section 8.3.2 section 8.3.3
Trait objects are dynamically sized, so they appear behind pointers:
- &dyn Trait borrows a value through the trait interface. section 8.3.2
- &mut dyn Trait borrows a value mutably through the trait interface. section 8.3.2
- Box<dyn Trait> owns the trait object. The Box pointer has a known size even when the value it points to does not. section 8.3.2 section 8.5.1
A party with different character types
Suppose Dwarf, Human, and Elf each implement Enchanter. A Vec needs one element type, so store references through their shared trait instead: `let party: Vec<&dyn Enchanter> = vec![&d, &h, &e];`. A randomly chosen member can then receive an `enchant` call. The caller uses the trait interface rather than the chosen character’s concrete type. section 8.3.1 section 8.3.3
One return type for different errors
An HTTP request can use `fn main() -> Result<(), Box<dyn Error>>`. The same pattern helps when `File::open()` and IPv6 address parsing can produce different errors: `?` can propagate them through one boxed error type. The trade-off is type erasure—the return type no longer identifies which upstream error type occurred. If later code must distinguish them, an enum wrapper can preserve them as variants. section 8.2 section 8.5.1 section 8.5.2
Generics offer the contrasting choice: static dispatch and faster runtimes, but potentially more compiled code. Trait objects add a small runtime cost through pointer indirection while allowing a single compiled version of a function. Use the trade-off that fits the job. section 8.3.2 section 8.11



