Tobias S.
Tobias S.

Reputation: 23795

What are "Blanket Implementations" in Rust?

When looking through the documentation of Rust structs, I often come across a section with the title "Blanket Implementations". I have heard that it can be used to implement a trait for all types or all types that match some condition but I am not sure why this is needed.

So what really are Blanket Implementations and why are they useful in Rust?

Upvotes: 17

Views: 8176

Answers (1)

kmdreko
kmdreko

Reputation: 59817

A blanket implementation is an implementation of a trait on a generic parameter:

impl<T> Trait for T

They usually also have where clauses involved since it is very hard to do anything useful to an unconstrained T. This does not cover things like impl<T> Trait for Vec<T>, which is a generic implementation but not a blanket implementation.

They are documented separately since they are applied without any particularity and may or may not be relevant to the type you're looking at. Whereas for the normal "Trait Implementations" section, all those traits at least had some thought for the specific type in mind (usually).

They are patently useful since it implements the trait for anything, in the entire ecosystem! If something satisfies the constraints, then it is able to take advantage of the implementation without needing to implement it themselves. You do not need to do anything to "opt-in" besides bringing the trait into scope.

Some notable ones:

  • From<T> is implemented for all T (the identity implementation)
  • Into<U> is implemented for all T where T: From<U> (the reflexive implementation that allows you to call .into() when a matching From implementation exists)
  • Any is implemented for all T where T: 'static

They are also needed to implement "trait aliases" where you create a trait that is constrained over multiple other traits (handy for reducing boilerplate and needed for multi-trait trait objects). You use a blanket implementation that the trait is implemented for any type satisfying the super-traits:

trait MyCoolAsyncTrait: AsyncRead + AsyncWrite + AsyncSeek + 'static {}

impl<T> MyCoolAsyncTrait for T 
where
    T: AsyncRead + AsyncWrite + AsyncSeek + 'static
{ }

Be careful when adding them to your types though. Because of their extensive scope, they can easily conflict with other trait implementations that may be desirable. You can only define one blanket implementation per type (even if the constraints are non-overlapping).

See also:

Upvotes: 25

Related Questions