development-programming-language-rust-traits.html


* created: 2025-07-17T12:02
* modified: 2025-10-15T11:19

title

Rust Traits

description

Traits are used to share functionality over multiple types. Furthermore we can define trait bounds that check if a type implements a certain trait and therefore has certain properties.

What are Traits?

Common Traits for Types

The following traits should generally be implemented by most of the types in a API:

  1. Debug, Clone
  2. Send, Sync, and Unpin
  3. PartialEq, PartialOrd, Hash, Eq and Ord
  4. Serialize and Deserialize (as opt in)

When using wrapper types the following traits should be implemented in addition: Deref, AsRef, From/Into<InnerType>, Borrow.

Exception

Copy: People generally don't expect types to implement Copy because it changes the move semantics of a given type, which might surprise user. It is often advisable to rely on Clone instead to explicitly create a a new copy. In addition Copy is highly restrictive and could result in a breaking change if a type has to rely on something like String further done the line.

dyn vs impl

Dynamic dispatch (dyn) allows for calling methods on trait objects at runtime, enabling polymorphism. If a function fn some(&dyn Trait) { ... } is called, it expects the input to be a pointer to a trait object (because the size is unknown during compile time). If mutability is needed use a Box<dyn Trait>.

Note: This is achieved using "fat pointers," which contain a pointer to the data and a pointer to a vtable that holds the method implementations for the specific type.

impl on the other hand uses static dispatch, which generates a separate version of the function at compile time for each concrete type used. This is referred to as monomorphization.