All methods in the io::Write
trait accept &mut self
. It makes sense since conceptually it needs to mutate some internal state. For the same reason, it is only natural to see it has a blanket implementation for &mut W
if W
is io::Write
:
impl<'_, W: Write + ?Sized> Write for &'_ mut W
On the other hand, I find it strange that it is also implemented for &File
and &TcpStream
in addition to File
and TcpStream
themselves.
This discrepancy bothers me a little bit. Is it done only for convenience? Or is it the nature of I/O make this safe?
Noticed this when trying out crate may
, a stackful coroutines library. Its net::TcpStream
doesn't have io::Write
implemented for &TcpStream
. So some code suddenly failed to compile:
use may::{coroutine::scope, go}; // may = "0.3"
use std::{
error::Error,
io::Write,
net::TcpStream,
};
fn send_to_peer(msg: &str, peer: &TcpStream) -> Result<(), Box<dyn Error>>
{
scope(|scope| {
go!(scope, move || {
let mut socket = peer;
let _ = socket.write_all(msg.as_bytes());
});
});
Ok(())
}
This compiles. Switch to may::net::TcpStream
and it will fail.