1

Let's say I have a trait IMyWriter that has a function flush_to_disk that gets an iterator of the pieces to write. Each piece that's written should yield a Result object.

use async_trait::async_trait;
use async_std::prelude::StreamExt;

#[async_trait]
trait IMyWriter<'a> {
   async fn flush_to_disk<'b, 'c: 'a + 'b, Iter, Results>(&mut self, pieces: Iter) -> Results 
    where
      Iter: IntoIterator<Item = u64>,
      Results: StreamExt<Item=Result<(), std::io::Error>>;
}

I'm having trouble with doing the mapping in the implementation:

use async_std::io::File;
use async_trait::async_trait;

struct MyWriter {
    file: Mutex<File>;
}

#[async_trait]
impl IMyWriter for MyWriter {
   async fn flush_to_disk<'b, 'c: 'a + 'b, Iter, Results>(&mut self, pieces: Iter) -> Results 
    where
      Iter: IntoIterator<Item = u64>,
      Results: StreamExt<Item=Result<(), std::io::Error>> {
      pieces.into_iter().map(|piece| async {
         let f = self.file.lock().await;
         // Do I/O on file
         Ok()
      })
   }
}

This obviously complains:

type parameter `Results`, found struct `std::iter::Map`

I can't for the life of me figure out how to return the results for the stream of asynchronous writes that happen.

Vitali
  • 3,411
  • 2
  • 24
  • 25
  • Does this answer your question? [Is it possible to use \`impl Trait\` as a function's return type in a trait definition?](https://stackoverflow.com/questions/39482131/is-it-possible-to-use-impl-trait-as-a-functions-return-type-in-a-trait-defini) – Aplet123 Dec 05 '20 at 20:43
  • I don't think so. I made a mistake transcribing the code. There's a missing #[async_trait] (so yes if you tried this as-written it won't compile). Fixing it now. The question itself still holds. How do I write a Rust function that returns a Stream (I think the async part is secondary but it's just what I had in the code I'm writing). – Vitali Dec 06 '20 at 03:22
  • Oh - and this is more closer to https://stackoverflow.com/questions/58700741/is-there-any-way-to-create-a-async-stream-generator-that-yields-the-result-of-re but the solution there is for tokio while this question is kind of for async_std (i.e. not using tokio unfold). – Vitali Dec 06 '20 at 03:25
  • Essentially, your error comes from the fact that you're returning **a** implementation of the `StreamExt` trait, not **every** implementation of the `StreamExt` trait, so a generic does not work in this situation (think about if the user specified a type for the `Results` generic parameter, how would you be able to return that?). The solution to this is generally to return `impl Trait` from a function, however that is not allowed within trait declarations, and workarounds are outlined in the question I previously sent, so hopefully you can find one that fits your needs. – Aplet123 Dec 06 '20 at 11:59
  • I think I'm too much of a n00b to go from that SO post to this specific use-case. I've tried a bunch of approaches but I can't figure out how to map it. Would you mind providing a concrete solution to this? – Vitali Dec 06 '20 at 19:19

0 Answers0