Regarding Pinning

use std::{time::Duration, pin::Pin};
use futures::FutureExt;
use tokio::time::Sleep;

fn unpin_or_not<F: Unpin>(_: F) {
}

#[tokio::main]
async fn main(){
    // let _f = tokio::time::sleep(Duration::from_secs(1));
    // unpin_or_not(_f); // not Unpin

    let ff = tokio::time::sleep(Duration::from_secs(1));
    let ff: Pin<Box<Sleep>> = Box::pin(ff);
    unpin_or_not(ff);

    let fff = tokio::time::sleep(Duration::from_secs(1));
    let fff: Pin<&mut Sleep> = unsafe { Pin::new_unchecked(&mut fff) };
    unpin_or_not(fff);

}

Pin<Box> is an owned pointer to a pinned T (taken from std::pin docs)

since it's just a pointer we can move it, but the underlying data is pinned.
since it's just a pointer it is Unpin.

Is the understanding correct regarding Unpin?

Yes, it is correct.

But you should be careful about calling Pin::new_unchecked. The data X it points to, sleep(1sec) in this case, must stay pinned even after Pin<&mut Sleep>'s usage ends, until itself (X) gets dropped. In this specifiec case from you example code, the original fff is shadowed so it's guaranteed, but it's not true in the general case.

1 Like