What you need is Pin
. It's a pointer that keeps your object from being moved.
pin_mut!()
is just a macro that helps you create a Pin
instance without heap allocation or unsafe
code.
PhantomPinned
has another, though related, goal. By default, your type will implement the Unpin
trait (unless it contains a type that don't implement Unpin
, however most types do). This is problematic, because for types that implements Unpin
, Pin
has no effect: it does not prevent you from moving them. This is because most types do not need a fixed memory address. Think about i32
, for example: even if you create Pin<&mut i32>
, you can move it, because i32
implements Unpin
, because even if you'll move it nothing bad will happen, and no data will be validated.
So for Pin
to be effective you need to un-impl Unpin
. This is done by either including a field that doesn't implements Unpin
itself as a field, or having a negative impl (see What is an auto trait in Rust?):
impl !Unpin for MyType {}
Unfortunately, negative impls are unstable. Instead, the standard library provides the PhantomPinned
type, which is costless (a ZST), but doesn't implement Unpin
(it has a negative impl, since the standard library is allowed to use unstable features it can do that). And now when your type includes it it becomes !Unpin
too.
To sum up, you need to include PhantomPinned
in your struct so it will not be Unpin
, and you need to wrap it in Pin
so it will be unmovable.