Dyn traits
Supporting dyn Trait
when Trait
contains an async fn
is challenging:
#![allow(unused)] fn main() { trait Trait { async fn foo(&self); } impl Trait for TypeA { async fn foo(&self); } impl Trait for TypeB { ... } }
Consider the desugared form of this trait:
#![allow(unused)] fn main() { trait Trait { type Foo<'s>: Future<Output = ()> + 's; fn foo(&self) -> Self::Foo<'_>; } impl Trait for TypeA { type Foo<'s> = impl Future<Output = ()> + 's; fn foo(&self) -> Self::Foo<'_> { async move { ... } // has some unique future type F_A } } impl Trait for TypeB { ... } }
The primary challenge to using dyn Trait
in today's Rust is that dyn Trait
today must list the values of all associated types. This means you would have to write dyn for<'s> Trait<Foo<'s> = XXX>
where XXX
is the future type defined by the impl, such as F_A
. This is not only verbose (or impossible), it also uniquely ties the dyn Trait
to a particular impl, defeating the whole point of dyn Trait
.
For this reason, the async_trait
crate models all futures as Box<dyn Future<...>>
:
#![allow(unused)] fn main() { #[async_trait] trait Trait { async fn foo(&self); } // desugars to trait Trait { fn foo(&self) -> Box<dyn Future<Output = ()> + Send + '_>; } }
This compiles, but it has downsides:
- Allocation is required, even when not using dyn Trait.
- The user must state up front whether
Box<dyn Future...>
isSend
or not.- In
async_trait
, this is declared by writing#[async_future(?Send)]
if desired.
- In
Desiderata
Here are some of the general constraints:
- The ability to use
async fn
in a trait without allocation - When using a
dyn Trait
, the type of the future must be the same for all impls- This implies a
Box
or other pointer indirection, or something like inline async fn.
- This implies a
- It would be nice if it were possible to use
dyn Trait
in an embedded context (without access toBox
)- This will not be possible "in general", but it could be possible for particular traits, such as
AsyncIterator
- This will not be possible "in general", but it could be possible for particular traits, such as