Where did Unique<T> go?

To quote myself, from that post @jbe linked to:

and elsewhere in this forum:

See also: this other post of mine over Zulip:

In practice #[may_dangle] by being not only unsafe, but unstable, is used in almost no libraries whatsoever (maybe some of the smallvec ones can let you opt into using them), and nobody is none the wiser: missing #[may_dangle] only hurts ergonomics in a quite negligible manner!

So, in practice, one could imagine that #[may_dangle] does not exist, and that this whole PhantomData-to-express-ownership-to-dropck is rather an interesting artifact from the past.

This is about the PtrThatOwns<T> aspect of Unique<T>, which is, thus, no longer relevant.


There is another way more interesting aspect about Unique<T>, which is that of being, as its name conveys, an unaliased pointer! (I don't know if Stacked Borrows uses this information, but it technically could). So the question now is: can we write our own unaliased (and thus dereferenceable) "raw" pointer abstraction? In practice, that alone isn't really possible, because of extra alignment requirements, which constrain the "higher-level" pointers able to convey lack of aliasing semantics (if we were able to express [MaybeUninit<u8>; size_of::<T>()] then we'd be able to lift the alignment requirements).

Expressing an unaliased well-aligned dereferenceable "raw" pointer

AFAIK, there is no clean way to achieve this, only "dirty hacks":

First attempt

If T : 'static, this seems to be easy:

#[repr(transparent)]
pub
struct UnaliasedDereferenceableWellAlignedPtr<T> (
    &'static mut MaybeUninit<T>,
);

It does come with an extra caveat, though: the obtained pointer ends up with shrunk provenance over that T and that T only, so that doing the following is Undefined Behavior:

let ptr: UnaliasedDereferenceableWellAlignedPtr<T> = …; // provenance over that `T`
let erased = ptr.cast::<()>; // provenance shrunk down to `()` = 0 bytes!
let ptr = erased.cast::<T>(); // UB: cannot be `dereferenceable` over a non-null span of bytes anymore!

That doesn't seem good for a "raw" pointer…

Second attempt

This is the only way I've managed to come up with, but at the cost of requiring alloc (:sob:):

#[repr(transparent)]
pub
struct UnaliasedWellAlignedPtr<T> (
    ManuallyDrop<Box<T>>,
);

we do lose the dereferenceable-ity, which is a pity, since if we are looking for unaliased optimizations, then we are likely to also want dereferenceable optimizations as well.

This is the approach taken by ::stackbox, for instance:

1 Like