
Description
Instead of re-exporting types Empty
, Sink
, and Cursor
from std::io
into async_std::io
, I believe we should create our own equivalents of those types.
The problem with these is that they implement synchronous and asynchronous traits at the same time, and I think that is a mistake. My intuition says that's wrong because types should either be synchronous or asynchronous, never both at the same time.
As a more concrete example, consider the fact that Sink
implements two methods write_all
, one coming from std::io::Write
and the other coming from async_std::io::Write
. Here's an attempt at calling write_all
while both traits are imported:
use std::io::prelude::*;
use async_std::io;
use async_std::prelude::*;
use async_std::task;
fn main() -> io::Result<()> {
task::block_on(async {
let s = io::sink();
s.write_all(b"hello world").await?;
Ok(())
})
}
This errors out with:
error[E0034]: multiple applicable items in scope
--> examples/foo.rs:10:11
|
10 | s.write_all(b"hello world").await?;
| ^^^^^^^^^ multiple `write_all` found
|
= note: candidate #1 is defined in an impl of the trait `std::io::Write` for the type `std::io::Sink`
= help: to disambiguate the method call, write `std::io::Write::write_all(s, b"hello world")` instead
= note: candidate #2 is defined in an impl of the trait `async_std::io::write::Write` for the type `_`
= help: to disambiguate the method call, write `async_std::io::write::Write::write_all(s, b"hello world")` instead
Having types that implement both synchronous and asynchronous traits at the same time is never a convenience, I think, and can only be a nuisance like in this example.
cc @yoshuawuyts