Expand description
Currently Rust does not support dynamic dispatch on traits that use async fn
or methods returning impl Trait
. Dynosaur is a proc macro that allows dynamic dispatch on these traits but uses static dispatch otherwise. It requires at least Rust 1.75.
This removes the need for the use of the async_trait
proc macro, giving users the performance benefits of static dispatch without giving up the flexibility of dynamic dispatch.
#[dynosaur::dynosaur(DynNext = dyn(box) Next)]
trait Next {
type Item;
async fn next(&mut self) -> Option<Self::Item>;
}
The macro above generates a type called DynNext
which can be used like this:
async fn dyn_dispatch(iter: &mut DynNext<'_, i32>) {
while let Some(item) = iter.next().await {
println!("- {item}");
}
}
let v = [1, 2, 3];
dyn_dispatch(&mut DynNext::boxed(my_next_iter)).await;
dyn_dispatch(DynNext::from_mut(&mut my_next_iter)).await;
Where my_next_iter
is a value of a type that you would create that implements Next
. For example:
struct MyNextIter<T: Copy> {
v: Vec<T>,
i: usize,
}
impl<T: Copy> Next for MyNextIter<T> {
type Item = T;
async fn next(&mut self) -> Option<Self::Item> {
if self.i >= self.v.len() {
return None;
}
do_some_async_work().await;
let item = self.v[self.i];
self.i += 1;
Some(item)
}
}
async fn do_some_async_work() {
// do something :)
}
The general rule is that anywhere you would write dyn Trait
(which would result in a compiler error), you instead write DynTrait
. Methods using impl Trait
box their return types when dispatched dynamically, but not when dispatched statically.
You can find more details in the API docs.
For more examples, take a look at dynosaur/examples
and dynosaur/tests/pass
. In tests you would find .rs
files with what the user would write and .stdout
files with what dynosaur generates.
§What will it take to implement this support in Rust?
There are many design questions to be answered before building this support into the language. You can find more background here: https://smallcultfollowing.com/babysteps/blog/2025/03/25/dyn-you-have-idea-for-dyn/.
§How does this crate solve this issue?
Given a trait MyTrait
, this crate generates a struct called DynMyTrait
that implements MyTrait
by delegating to the actual impls on the concrete type and wrapping the result in a box. For more details on what is exactly generated you may want to check .stdout
files in dynosaur/tests/pass
.
§License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Attribute Macros§
- dynosaur
- Create a struct that takes the place of
dyn Trait
for a trait, supporting bothasync
and-> impl Trait
methods.