I'd like a function which asynchronously processes a variable amount of (Sink
, Stream
) tuples.
use futures::channel::mpsc;
use futures::{Sink, Stream, SinkExt, StreamExt};
async fn foo(v: Vec<(Box<dyn Sink<Error = std::io::Error>>, Box<dyn Stream<Item = u8>>)>) {
for (mut tx, mut rx) in v {
let _ = tx.send(0);
let _ = rx.next().await;
}
}
#[tokio::main]
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
let (tx, mut rx) = mpsc::channel(32);
foo(vec![(Box::new(tx), Box::new(rx))]).await;
Ok(())
}
But I get this compilation error:
error[E0107]: wrong number of type arguments: expected 1, found 0 --> src/main.rs:4:30 | 4 | async fn foo(v: Vec<(Box<dyn Sink<Error = std::io::Error>>, Box<dyn Stream<Item = u8>>)>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument
I was prompted to declare the associated type for the trait object that way by the compiler itself. I'm unsure why it does not accept it.
The compiler wants you to specify the "type argument" of the
Sink
. This is not the error type, but the type of the item being sent down the sink, as inSink<Foo>
. You specifyu8
as the type of the stream, and are sending the value unchanged between one and the other, so you probably want aSink<u8>
.Once you do that, the compiler will next complain that you need to specify the
Error
associated type (this time for real). However if you specifystd::io::Error
, the call tofoo()
frommain()
won't compile because the implementation ofSink
formpsc::Sender
specifies its ownmpsc::SendError
as the error type.Finally, both the sink and the stream need to be pinned so they can live across await points. This is done by using
Pin<Box<...>>
instead ofBox<...>
andBox::pin(...)
instead ofBox::new(...)
.With the above changes, a version that compiles looks like this: