This is my struct (for completeness sake):
struct Client<'a, T>
where
T: AsyncRead + AsyncWrite + Unpin
{
socket: T,
stage: u8,
n: usize,
buf: &'a mut [u8],
}
I then implemented a Future
for the struct, but changed self
to me
via let me = &mut *self;
.
This compiles fine:
impl<'a, T> Future for Client<'a, T>
where
T: AsyncRead + AsyncWrite + Unpin
{
type Output = io::Result<()>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let me = &mut *self; // <<<<<<<<<< this fixes it, how?!
while me.stage == 1 {
let self_n = me.n;
let mut rb = ReadBuf::new(&mut me.buf[..self_n]);
let n = ready!(Pin::new(&mut me.socket).poll_read(cx, &mut rb));
}
Poll::Pending
}
}
however, if I remove that conversion, it will trigger a borrow checker error:
impl<'a, T> Future for Client<'a, T>
where
T: AsyncRead + AsyncWrite + Unpin
{
type Output = io::Result<()>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// magic line removed
while self.stage == 1 {
let self_n = self.n;
let mut rb = ReadBuf::new(&mut self.buf[..self_n]);
let n = ready!(Pin::new(&mut self.socket).poll_read(cx, &mut rb));
}
Poll::Pending
}
}
error[E0499]: cannot borrow `self` as mutable more than once at a time
--> z.rs:y:x
|
84 | let mut rb = ReadBuf::new(&mut self.buf[..RES.len() - self_n]);
| ---- first mutable borrow occurs here
85 | let n = ready!(Pin::new(&mut self.socket).poll_read(cx, &mut rb));
| ^^^^ ------- first borrow later used here
| |
| second mutable borrow occurs here
What is it about let me = &mut *self;
that gets it compiled?
As seen in this thread, mutably borrowing an element of a Pin
requires using its DerefMut
implementation, which mutably borrows the entire Pin
. Thus, you cannot mutably borrow 2 fields, even if they are disjoint. The line let me = &mut *self
(or alternatively let me = &mut self
) uses Pin
's DerefMut
implementation to generate a &mut Self
from the Pin<&mut Self>
. It only does this once, then two disjoint fields are borrowed through that mutable borrow, which leads to no errors.