Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why we use `Box::pin` for !Unpin and `Pin::new` for Unpin?

Tags:

rust

I get confused when learning implementation of Pin in rust.

I understand when a type is not safe to move, it can impl !Unpin. Pin is to prevent others get &mut T from these types, so that they can not be std::mem::swap.

If Pin is designed for !Unpin types, why we can't just call Pin::new on those types?

It gives error like the following. I know I should use Pin::new_unchecked, but why?

struct TestNUnpin {
    b: String,
}
impl !Unpin for TestNUnpin {}

// error: the trait `Unpin` is not implemented for `TestNUnpin`
std::pin::Pin::new(&TestNUnpin{b: "b".to_owned()});

My reasoning is:

  1. Pin is to help !Unpin types
  2. We can pass !Unpin types to Pin::new to make them unmovable.
  3. For Unpin types, they can not be pinned, so we can't created by Pin::new
like image 225
calvin Avatar asked Oct 19 '25 06:10

calvin


1 Answers

I think what you're looking for can be found in the Safety section of Pin::new_unchecked. Essentially, Pin should guarantee that the pinned value will never move again (unless it implements Unpin), even after the Pin is dropped. An example of this failing is Pin<&mut T>. You can drop the Pin and the value is no longer borrowed, so you're free to move it again, breaking Pin's core guarantee. Here's an example:

use std::marker::PhantomPinned;
use std::pin::Pin;

fn main() {
    let x = PhantomPinned;
    
    {
        let _pin = Pin::new(&x); // error[E0277]: `PhantomPinned` cannot be unpinned
    }

    let y = Box::new(x); // the PhantomPinned is moved here!
}

This check simply isn't doable at compile-time without adding a whole lot of extra complexity to the borrow checker, so it's marked as unsafe, essentially saying it's the developer's job to make sure it works. The reason Box::pin exists and is safe is because the developers of Box can guarantee its safety: Box is an owned and unique pointer, so once its Pin is dropped, its value is also dropped, and there's no longer any way to move the value.

like image 76
Aplet123 Avatar answered Oct 20 '25 23:10

Aplet123



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!