Here is the code:
&TcpStream will be get after self.stream.as_ref().unwrap()
but it compiles ok with calling write which need &mut self
Am I missing about the implicit conversion?
Here is the code:
&TcpStream will be get after self.stream.as_ref().unwrap()
but it compiles ok with calling write which need &mut self
Am I missing about the implicit conversion?
Self is &TcpStream here (instead of TcpStream
.)
Yes,I got it. Thanks
But write still need a mutable reference for &TcpStream , so it should be a type of &mut &TcpStream that can call the write function.
but in my post, it still a immutable reference( &TcpStream) after self.stream.as_ref().unwrap()
It's trivial to create a [1] The compiler does so under the hood of method-call expressions:&mut &T
from a &T
given that references are copy.
The first step is to build a list of candidate receiver types. Obtain these by repeatedly dereferencing the receiver expression’s type, adding each type encountered to the list, then finally attempting an unsized coercion at the end, and adding the result type if that is successful. Then, for each candidate
T
, add&T
and&mut T
to the list immediately afterT
.
Irrelevant, see @SebastianJL comment below. ↩︎
No, you cannot modify data through a shared reference.
The magic lies in that the inner TcpStream
uses internal mutability:
via
Is that even necessary? The compiler will also create a &mut T
from a T
in methods even when T: !Copy
.
Sure, that's the reason why Write
can be implemented for &TcpStream
. It does not change how Rustc creates a &mut &TcpStream
from &TcpStream
to satisfy the signature of <&TcpStream as Write>::write
.
Of course. Thanks for the correction.
I check the docs, I can't understand why immutable T
can be listed as candidate with type of &mut T
, This obviously violates the borrowing rule
That does not violate the borrowing rules because you can't mutate TcpStream
if you have &mut &TcpStream
(the mutability of the outer reference only allows you to change the &TcpStream
to be a different immutable reference, i.e. to a different TcpStream
). Maybe you find it helpful if we were to desugar your example a bit and use fully qualified syntax instead of relying on method-call resolution?
fn send(&mut self,data: &[u8])->usize
{
let x: Option<&TcpStream> = self.stream.as_ref();
let mut x: &TcpStream = x.unwrap();
<&TcpStream as Write>::write(&mut x, data).unwrap()
}
so the mut
before x is the key! if T was declared as a mut T
(mutable), so it can be listed as candidate with type &mut T
; if T was declared as a T
(immutable), the compiler should not use &mut T
as a candidate .
What you might missed is that, mutability is a property of binding, not value (or type). You can always write let mut x = x;
to declare a new mut
binding to the value.
Since your original code snippet, the concerning value is a temporary, it's free to assign a mut
binding to it.
Thanks, these words hit my doubts.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.