#![allow(dead_code, deprecated, unused_variables, unused_mut)] use std::pin::Pin; use std::marker::PhantomPinned; use std::ptr::NonNull; /// This is a self-referential struct because `self.slice` points into `self.data`. struct Unmovable { /// Backing buffer. data: [u8; 64], /// Points at `self.data` which we know is itself non-null. Raw pointer because we can't do /// this with a normal reference. slice: NonNull<[u8]>, /// Suppress `Unpin` so that this cannot be moved out of a `Pin` once constructed. _pin: PhantomPinned, } impl Unmovable { /// Creates a new `Unmovable`. /// /// To ensure the data doesn't move we place it on the heap behind a pinning Box. /// Note that the data is pinned, but the `Pin>` which is pinning it can /// itself still be moved. This is important because it means we can return the pinning /// pointer from the function, which is itself a kind of move! fn new() -> Pin> { let res = Unmovable { data: [0; 64], slice: NonNull::from(&[]), _pin: PhantomPinned, }; let mut boxed = Box::new(res); boxed.slice = NonNull::from(&boxed.data); let pin = Box::into_pin(boxed); pin } } fn main() { let unmovable: Pin> = Unmovable::new(); #[allow(unused_mut)] let mut still_unmoved = unmovable; assert_eq!(still_unmoved.slice, NonNull::from(& still_unmoved.data)); }