Use `dyn Trait` when code needs to hold a value through a trait rather than name its concrete type. A trait object supports dynamic dispatch: method calls use a vtable lookup. For example, `Box<dyn MyTrait>` stores a value that implements `MyTrait`. That runtime lookup is a trade-off to consider in a tight loop. section 11.1
Trait objects are useful when a trait method must return a future but the implementation’s future type cannot be named as an associated type. An async observer can return `Pin<Box<dyn Future<Output = Self::Output> + 'a + Send>>`. The box holds the trait object; pinning lets the future be polled by `.await`. A plain `Box<dyn Future<…>>` fails here because the boxed future is not necessarily `Unpin`. section 8.6
Listing 8.4 Implementing the async Observer trait
pub trait Observer: Send + Sync { #1
type Subject;
type Output;
fn observe<'a>( #2
&'a self, #3
subject: &'a Self::Subject, #4
) -> Pin<Box<dyn Future<Output = Self::Output> + 'a + Send>>; #5
}
The observer signature ties the returned future to the lifetimes of both borrowed inputs and requires the future to be `Send`. section 8.6
The same technique provides a simple error return type: `Result<(), Box<dyn std::error::Error + Send + Sync>>` lets `?` surface errors through a CLI. It works when the errors implement `std::error::Error`, but it is a deliberately simple choice. If error-specific handling, logging, or messages matter, define an error type and use `From` to convert errors instead. section 10.6 section 10.8



