About

Traits & Generics — Polymorphism in Rust

Rust's abstraction tool: interfaces + generics combined

Traits define "this type can do this behavior." Like Java interfaces, but you can implement a trait for existing types after the fact.

trait Summary {
    fn summarize(&self) -> String;
}

With where T: Summary trait bounds in generic functions, the compiler generates separate functions per concrete type (monomorphization) — zero vtable cost at runtime.

dyn Trait enables runtime polymorphism (dynamic dispatch) through vtable indirect calls.

Key Points

1

Define common behavior (method signatures) with traits

2

Implement for concrete types with impl Trait for Type

3

Generics + trait bounds for compile-time polymorphism (static dispatch)

4

dyn Trait for runtime polymorphism when needed (dynamic dispatch)

Pros

  • ✓ Zero-cost abstraction — generics inlined via monomorphization
  • ✓ Retroactive implementation on existing types (within orphan rule)

Cons

  • ✗ Monomorphization can increase binary size
  • ✗ Complex trait bounds lead to long where clauses

Use Cases

Serialization — serde Serialize/Deserialize traits Async runtime — Future trait-based async/await

References

← Result and the ? Operator — Rust Error Handling Patterns Enum, Option, Result — Algebraic Data Types in Rust →