Does pinning require a stable deref?

In other words, is the following type valid to put into Pin::new_unchecked with !Unpin types?

struct RngBox<T> {
    left: Box<T>,
    right: Box<T>,
}

impl<T> Deref for RngBox<T> {
    type Target = T;
    fn deref(&self) -> &T {
        if ::rand::random() {
            &*self.left
        } else {
            &*self.right
        }
    }
}

This type is not StableDeref, as StableDeref requires that all instances of calling <Self as Deref>::deref produce the same reference. As for what I'm reading, Pin has no such requirement; it only requires that <P as Deref>::deref does not move from &self and that it's not possible to go from Pin<P> to &mut Target (safely). As far as I can tell, RngBox meets all the requirements of Pin::new_unchecked, as it does not require a consistent deref location, just that said deref locations are valid and not moved from.

Similarly, is there a requirement that Deref and DerefMut go to the same place? That requirement is present in StableDeref. I don't think so, but wouldn't be surprised if some things were subtly relying on that to be true.

I don't believe the docs imply anything regarding interactions with Deref, only the value is guaranteed not to move, so it is safe to store self referencing pointers.

1 Like

I think we can use the same justification as how Box::pin (which is ultimately calling Pin::new_unchecked) is used to pin any T: !Unpin here. More specifically,

// It's not possible to move or replace the insides of a Pin<Box<T>>
// when T: !Unpin, so it's safe to pin it directly without any
// additional requirements.

So it is safe to use Pin::new_unchecked and the fact that where the internal fields are pointing to and how RngBox is dereferenced doesn't matter.

Btw, continuing from my Rust Std Study Series I happen to post about pin just today :sweat_smile:

The way I see the RngBox is as a Box<[T; N]> (e.g., Box<[T; 2]>) offering pinning projections to each one of its "cells".

The deref is then just randomly indexing, but since each "cell" acts itself as pinned, it should not be a problem.

1 Like