In async program what's different about thoose two poll call

the first case it will compile failed. throw thoose error

error[E0507]: cannot move out of dereference of `Pin<&mut TestFuture<'_>>`
  --> src/lib.rs:19:18
   |
19 |         Pin::new(self.0).poll_with_pin_self(cx)
   |                  ^^^^^^ move occurs because value has type `&mut NonCopyStruct`, which does not implement the `Copy` trait

For more information about this error, try `rustc --explain E0507`.

i don't understand the Copy trait bound where is found and i don't know what's different about second case. but second case working fine.

here's the main different

Pin::new(self.0).poll_with_pin_self(cx)

and

NonCopyStruct::poll_with_pin_self(Pin::new(self.0), cx)

This change to the first case compiles:

-    fn poll(    self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
-        Pin::new(      self.0).poll_with_pin_self(cx)
+        Pin::new(&mut *self.0).poll_with_pin_self(cx)
     }

&mut *self.0 is a reborrow. These usually happen automatically, but when the the &mut _ matches against a generic type parameter, such as Ptr in Pin::<Ptr>::new, they do not happen automatically. So the original code was trying to move the self.0 field instead of reborrowing *self.0.

The second case explicitly has a Pin<&mut _> in the function signature, which allows automatic reborrowing to kick in.

3 Likes

thanks for you explanation