Safe stack pinning without macro

This. I see no difference between let pin foo = …; and let foo = pin!(…);, but for the former to be more restrictive than pin!() which can be inlined within a function call. pin!() is the counterpart of Box::pin, which also elegantly ties it back up to this Anchor / Pin historical debut. While pin-as-a-keyword could be useful as a more general tool (mainly: pinning projections, but those would require Unpin lack of unsafe to be fixed), until then I don't think saving an exclamation mark warrants adding a dedicated keyword.

Speaking of which, it would be nice if there could be some movement over:


Regarding the OP, their invention is basically &own, which can be quite useful independently of pinning, and there is no &own counter-part of Box::pin since a &own, contrary to a Box, borrows the backing storage, and thus cannot enforce the pinning guarantee.

FWIW, there is an interesting variant that that exploits "maximal self-lifetime" to almost reach the desired effect:

use ::core::pin::Pin;

struct PinnableSlot<'r, T> {
    value: T,
    _invariant_lt: ::core::marker::PhantomData<&'r mut &'r ()>,
}

impl<'r, T> PinnableSlot<'r, T> {
    //            maximally-long `&mut` borrow
    //               vv                  vv
    fn pinned(self: &'r mut PinnableSlot<'r, T>)
      -> Pin<&'r mut T>
    {
        unsafe { Pin::new_unchecked(&mut self.value) }
    }
}

Usage being:

let mut slot = PinnableSlot::new(…);
let thing: Pin<&mut …> = slot.pinned(); // `&mut` is maximal thanks to lifetimes;
                                        // effectively "pinning" it.

Alas, this does not work due to ManuallyDrop:

let slot = PinnableSlot::new(…);
let mut slot_without_drop = ManuallyDrop::new(slot);
let thing: Pin<&mut …> = slot_without_drop.pinned(); // Uh-oh

Playground

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.