As I was trying to understand the differences between a mutable variable, which happens to be a reference, e.g. let mut x: &i32 vs mutable references, e.g. let x: &mut i32, I found this difference I can't understand:
This works, where by_ref has the signature: fn by_ref(&mut self) -> &mut Self (docs)
fn example(mut t: &TcpStream) {
t.by_ref();
}
But the following with String, using a method with a similar looking signature, reserve:
pub fn reserve(&mut self, additional: usize)
But this does not work, the error is:
"cannot borrow
*stras mutable, as it is behind a&reference"
fn example(mut str: &String) {
str.reserve(10);
}
Interesting to note that these two examples with mutable references work, and are, as far I know, the recommended way to use mutable methods:
fn example_stream(t: &mut TcpStream) {
t.by_ref();
}
fn example_string(str: &mut String) {
str.reserve(10);
}
So what is different between a TcpStream and a String that allows methods with a &mut self argument to be called in one case and not in the other?
Your TcpStream sample is misleading you.
There is impl Read for TcpStream as you've linked to, but there is also impl Read for &TcpStream. You are actually using the latter which does not need mutable access to the TcpStream, only mutable access to the reference to the TcpStream, which is t.
This is done because the Read trait uses mutable methods to allow readers that need mutation or exclusive access to read. However TcpStream actually doesn't need mutation or exclusive access to read data since it essentially just defers to a syscall. Because of this, TcpStream can be more flexible and allow multiple threads to read/write from a socket by implementing Read on its reference.
The str.reserve() call, on the otherhand, does not have this luxury and requires mutable access to the String itself, and thus a &String is not enough.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With