Is pinning reversible?

Hello all,

I know that when a type implements !Unpin, it can still be moved before being pinned for the first time, like a future before it is ever polled. Is it possible to do the opposite, i.e. transition a self-referential object into a state where there are no more self-references and then move it again? Reading the documentation for Pin::into_inner_unchecked gives me the impression that it's illegal to do so even if the object is in a state where it can be moved without invalidating any references (i.e. when you have full ownership and when there are no self-references).

Am I missing something here or is this intentional? I can always work around it by aping C++-style move semantics (moving doesn't destroy the original, it just leaves a valid but empty object in place, which would remain pinned), but that is rather unsatisfying IMO.

It's entirely possible that a type that doesn't implement Unpin still provides some API for transitioning from pinned to non-pinned, so e. g. Pin<Box<Self>>) -> Box<Self>. Just as someone implementing a type can choose to implement Unpin, they could choose to offer such a function, there's no safety problems with that.

The documentation of Pin::into_inner_unchecked assumes that you're handling some type Pin<P> where you aren't having any additional information on the P::Target type. Often, this might trivially be the case when that target type is just a generic parameter. On the other hand, for example if P::Target is known to be some concrete type and you're the author of that type (or the author of the type gave you some additional guarantees that allow it under certain circumstances), moving the type after it was pinned can be fine.

One could try to make this generic, e. g. through a trait

unsafe trait PackPinned {
    fn pack_pinned(&mut Self);
}

that then provides all kinds of helper functions like a

fn pack_box<T: PackPinned>(x: Box<Pin<T>>) -> Box<T>

or

fn pack_mut<T: PackPinned>(x: Pin<&mut T>)-> &mut T

by calling pack_pinned on the contained value first before moving / exposing it. The unsafe trait would need to be documented with some safety conditions that make sure that these helper functions are sound.

The naming of all of these is probably suboptimal, I'm focusing on the type signatures here

Thanks, that was what I needed to know.

It's hard to know, however, judging only from the docs (from Pin in std::pin - Rust (rust-lang.org)):

A value, once pinned, must remain pinned forever (unless its type implements Unpin).

And many statements like that.

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.