I am trying to create a async_trait that use a dyn reference to Iterator.
Here is an example of my code :
#[async_trait::async_trait]
trait StringPrinter {
async fn print(a: &mut dyn Iterator<Item = String>);
}
struct MyStringPrinter{}
#[async_trait::async_trait]
impl StringPrinter for MyStringPrinter {
async fn print(a: &mut dyn Iterator<Item = String>){
a.for_each(|x| println!("{}", x));
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}
}
But the compiler complains on : future created by async block is not 'Send'
On the other hand - simple version of async function works well:
async fn print_iterator(a: &mut dyn Iterator<Item = String>) {
a.for_each(|x| println!("{}", x));
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}
Any idea what is different ? or any idea for workaround?
Yes, it is possible, after all the #[async_trait]
proc-macro rewrites the method to use a boxed future. This is explained in the documentation of the crate:
Async fns get transformed into methods that return
Pin<Box<dyn Future + Send + 'async>>
and delegate to a privateasync
freestanding function.
But generated future will be Send
if and only if all its members implement Send
. Yet your iterator does not:
&mut dyn Iterator<Item = String>
Just change that to:
&mut (dyn Iterator<Item = String> + Send)