moveit/
move_ref.rs

1// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Move references.
16//!
17//! A move reference represents an owned value that is stored "somewhere else".
18//! We own the value, not the storage.
19//!
20//! A [`MoveRef<'a, T>`] represents a *permanent* unique reference to `T` for
21//! the lifetime `'a`: it is the longest-lived *possible* reference to the
22//! pointee, making it closer to a [`Box<T>`]
23//!
24//! Like [`&mut T`] but unlike [`Box<T>`], a [`MoveRef<T>`] is not responsible
25//! for destroying its storage, meaning that it is storage agnostic. The storage
26//! might be on the stack *or* on the heap; some RAII value on the stack is
27//! responsible for destroying just the storage, once the [`MoveRef<T>`] itself
28//! is gone.
29//!
30//! The main mechanism for obtaining [`MoveRef`]s is the [`moveit!()`] macro,
31//! which is analogous to a theoretical `&move expr` operator. This macro
32//! wraps [`DerefMove`], much like `&mut expr` wraps [`DerefMut`].
33//!
34//! Implementing [`DerefMove`] is a delicate affair; its documentation details
35//! exactly how it should be done.
36//!
37//! # Drop Flags
38//!
39//! In order to be sound, a `MoveRef` must also hold a pointer to a drop flag,
40//! which is used to detect if the `MoveRef` was dropped without destruction.
41//!
42//! In general, [`mem::forget`]ing a `MoveRef` is a very, very bad idea. In the
43//! best case it will leak memory, but in some cases will crash the program in
44//! order to observe safety guarantees.
45
46use core::mem;
47use core::ops::Deref;
48use core::ops::DerefMut;
49use core::pin::Pin;
50use core::ptr;
51
52#[cfg(doc)]
53use {
54  crate::{drop_flag, moveit},
55  alloc::{boxed::Box, rc::Rc, sync::Arc},
56  core::mem::{ManuallyDrop, MaybeUninit},
57};
58
59use crate::drop_flag::DropFlag;
60use crate::slot::DroppingSlot;
61
62/// A `MoveRef<'a, T>` represents an owned `T` whose storage location is valid
63/// but unspecified.
64///
65/// See [the module documentation][self] for more details.
66pub struct MoveRef<'a, T: ?Sized> {
67  ptr: &'a mut T,
68  drop_flag: DropFlag<'a>,
69}
70
71impl<'a, T: ?Sized> MoveRef<'a, T> {
72  /// Creates a new `MoveRef<T>` out of a mutable reference.
73  ///
74  /// # Safety
75  ///
76  /// `ptr` must satisfy the *longest-lived* criterion: after the return value
77  /// goes out of scope, `ptr` must also be out-of-scope. Calling this function
78  /// correctly is non-trivial, and should be left to [`moveit!()`] instead.
79  ///
80  /// In particular, if `ptr` outlives the returned `MoveRef`, it will point
81  /// to dropped memory, which is UB.
82  ///
83  /// `drop_flag`'s value must not be dead, and must be a drop flag governing
84  /// the destruction of `ptr`'s storage in an appropriate manner as described
85  /// in [`moveit::drop_flag`][crate::drop_flag].
86  #[inline]
87  pub unsafe fn new_unchecked(ptr: &'a mut T, drop_flag: DropFlag<'a>) -> Self {
88    Self { ptr, drop_flag }
89  }
90
91  /// Converts a `MoveRef<T>` into a `Pin<MoveRef<T>>`.
92  ///
93  /// Because we own the referent, we are entitled to pin it permanently. See
94  /// [`Box::into_pin()`] for a standard-library equivalent.
95  #[inline]
96  pub fn into_pin(this: Self) -> Pin<Self> {
97    unsafe { Pin::new_unchecked(this) }
98  }
99
100  /// Returns this `MoveRef<T>` as a raw pointer, without creating an
101  /// intermediate reference.
102  ///
103  /// The usual caveats for casting a reference to a pointer apply.
104  #[inline]
105  pub fn as_ptr(this: &Self) -> *const T {
106    this.ptr
107  }
108
109  /// Returns this `MoveRef<T>` as a raw mutable pointer, without creating an
110  /// intermediate reference.
111  ///
112  /// The usual caveats for casting a reference to a pointer apply.
113  #[inline]
114  pub fn as_mut_ptr(this: &mut Self) -> *mut T {
115    this.ptr
116  }
117
118  #[allow(unused)]
119  pub(crate) fn drop_flag(this: &Self) -> DropFlag<'a> {
120    this.drop_flag
121  }
122}
123
124// Extremely dangerous casts used by DerefMove below.
125impl<'a, T> MoveRef<'a, T> {
126  /// Consumes `self`, blindly casting the inner pointer to `U`.
127  pub(crate) unsafe fn cast<U>(mut self) -> MoveRef<'a, U> {
128    let mr = MoveRef {
129      ptr: &mut *Self::as_mut_ptr(&mut self).cast(),
130      drop_flag: self.drop_flag,
131    };
132    mem::forget(self);
133    mr
134  }
135}
136
137impl<'a, T> MoveRef<'a, T> {
138  /// Consume the `MoveRef<T>`, returning the wrapped value.
139  #[inline]
140  pub fn into_inner(this: Self) -> T {
141    unsafe {
142      let val = ptr::read(this.ptr);
143      let _ = this.cast::<()>();
144      val
145    }
146  }
147}
148
149impl<T: ?Sized> Deref for MoveRef<'_, T> {
150  type Target = T;
151
152  #[inline]
153  fn deref(&self) -> &Self::Target {
154    self.ptr
155  }
156}
157
158impl<T: ?Sized> DerefMut for MoveRef<'_, T> {
159  #[inline]
160  fn deref_mut(&mut self) -> &mut Self::Target {
161    self.ptr
162  }
163}
164
165impl<T: ?Sized> Drop for MoveRef<'_, T> {
166  #[inline]
167  fn drop(&mut self) {
168    self.drop_flag.dec_and_check_if_died();
169    unsafe { ptr::drop_in_place(self.ptr) }
170  }
171}
172
173impl<'a, T> From<MoveRef<'a, T>> for Pin<MoveRef<'a, T>> {
174  #[inline]
175  fn from(x: MoveRef<'a, T>) -> Self {
176    MoveRef::into_pin(x)
177  }
178}
179
180/// A trait for getting a pinned [`MoveRef`] for some pointer type `Self`.
181///
182/// Conceptually, this trait is similar to [`DerefMove`], except that where
183/// [`DerefMove::deref_move`] produces a `MoveRef<T>`, [`AsMove::as_move`] produces a
184/// `Pin<MoveRef<T>>`.
185///
186/// `DerefMove` can be seen as a refinement of `AsMove` where stronger guarantees about the memory
187/// behavior (specifically the Pin-safety) of `Self` are present.
188///
189/// Codifying this notion is the fact that `DerefMove` requires that `Self: DerefMut + AsMove`,
190/// whereas `AsMove` only requires the weaker constraints of `Self: Deref`.
191///
192/// Although `AsMove` is a supertrait of `DerefMove`, but `DerefMove` is *not* a supertrait of
193/// `AsMove`, the two traits are nevertheless intended to have their impls for a given type defined
194/// together *simultanteously*.
195///
196/// It is expected in this situation that the impl for one of the traits will be (trivially) defined
197/// in terms of the other, depending on the API for the pointer type `Self` with respect to
198/// [`DerefMut`].
199///
200/// For example, the `Box<T>: AsMove` impl is defined in terms of the `Box<T>: DerefMove` impl,
201/// because it is always the case that `Box<T>: DerefMut` regardless of whether `T: Unpin`. Hence,
202/// `Box<T>: AsMove` simply performs the `Box<T>: DerefMove` operation then subsequently
203/// (and trivially) pins the resulting `MoveRef<T>` with [`MoveRef::into_pin`].
204///
205/// On the other hand, the `cxx::UniquePtr<T>: DerefMove` impl is defined in terms of the
206/// `UniquePtr<T>: AsMove` impl, because a `cxx::UniquePtr<T>: DerefMut` only if `T: Unpin`. Given
207/// that `cxx::UniquePtr<T>` behaves like `Pin<Box<T>>` with respect to `DerefMut`, it is always
208/// possible to safely produce a `Pin<MoveRef<T>>`, but *not* always possible to safely produce a
209/// `MoveRef<T>`. Hence, when `T: Unpin`, only then `cxx::UniquePtr<T>: DerefMove` is defined,
210/// which simply performs the `cxx::UniquePtr<T>: AsMove` operation then subsequently
211/// (and trivially) unpins the resulting `Pin<MoveRef<T>>` with [`Pin::into_inner`].
212pub trait AsMove: Deref + Sized {
213  /// The "pure storage" form of `Self`, which owns the storage but not the
214  /// pointee.
215  type Storage: Sized;
216
217  /// Gets a pinned `MoveRef` out of `Self`.
218  ///
219  /// This function is best paired with [`moveit!()`]:
220  /// ```
221  /// # use core::pin::Pin;
222  /// # use moveit::{moveit, slot::DroppingSlot, move_ref::AsMove};
223  /// let ptr = Box::pin(5);
224  /// moveit::slot!(#[dropping] storage);
225  /// ptr.as_move(storage);
226  /// ```
227  /// Taking a trip through [`moveit!()`] is unavoidable due to the nature of
228  /// `MoveRef`.
229  ///
230  /// Compare with [`Pin::as_mut()`].
231  fn as_move<'frame>(
232    self,
233    storage: DroppingSlot<'frame, Self::Storage>,
234  ) -> Pin<MoveRef<'frame, Self::Target>>
235  where
236    Self: 'frame;
237}
238
239impl<'f, T: ?Sized> AsMove for MoveRef<'f, T> {
240  type Storage = ();
241
242  #[inline]
243  fn as_move<'frame>(
244    self,
245    storage: DroppingSlot<'frame, Self::Storage>,
246  ) -> Pin<MoveRef<'frame, Self::Target>>
247  where
248    Self: 'frame,
249  {
250    MoveRef::into_pin(DerefMove::deref_move(self, storage))
251  }
252}
253
254impl<P: DerefMove> AsMove for Pin<P> {
255  type Storage = P::Storage;
256
257  #[inline]
258  fn as_move<'frame>(
259    self,
260    storage: DroppingSlot<'frame, Self::Storage>,
261  ) -> Pin<MoveRef<'frame, Self::Target>>
262  where
263    Self: 'frame,
264  {
265    unsafe {
266      // SAFETY:
267      //
268      // It is safe to unwrap the `Pin` because `deref_move()` must not move out of the actual
269      // storage, merely shuffle pointers around, and immediately after the call to `deref_move()`
270      // we repin with `MoveRef::into_pin`, so the `Pin` API invariants are not violated later.
271      MoveRef::into_pin(P::deref_move(Pin::into_inner_unchecked(self), storage))
272    }
273  }
274}
275
276/// Moving dereference operations.
277///
278/// *Note: This trait is intended to be defined in conjunction with [`AsMove`],
279/// and there is a subtle interdependency between the two traits. We recommend
280/// also reading it's documentation for a better understanding of how these
281/// traits fit together.*
282///
283/// This trait is the `&move` analogue of [`Deref`], for taking a pointer that
284/// is the *sole owner* its pointee and converting it to a [`MoveRef`]. In
285/// particular, a pointer type `P` owns its contents if dropping it would cause
286/// its pointee's destructor to run.
287///
288/// For example:
289/// - [`MoveRef<T>`] implements `DerefMove` by definition.
290/// - [`Box<T>`] implements `DerefMove`, since it drops the `T` in its
291///   destructor.
292/// - [`&mut T`] does *not* implement `DerefMove`, because it is
293///   necessarily a borrow of a longer-lived, "truly owning" reference.
294/// - [`Rc<T>`] and [`Arc<T>`] do *not* implement `DerefMove`, because even
295///   though they own their pointees, they are not the *sole* owners. Dropping
296///   a reference-counted pointer need not run the destructor if other pointers
297///   are still alive.
298/// - [`Pin<P>`] for `P: DerefMove` implements `DerefMove` only when
299///   `P::Target: Unpin`, since `DerefMove: DerefMut`.
300///
301/// # Principle of Operation
302///
303/// Unfortunately, because we don't yet have language support for `&move`, we
304/// need to break the implementation into two steps:
305/// - Inhibit the "inner destructor" of the pointee, so that the smart pointer
306///   is now managing dumb bytes. This is usually accomplished by converting the
307///   pointee type to [`MaybeUninit<T>`].
308/// - Extract a [`MoveRef`] out of the "deinitialized" pointer.
309///
310/// The first part of this consists of converting the pointer into the
311/// "partially deinitialized" form, represented by the type
312/// [`AsMove::Storage`]: it is the pointer as "pure storage".
313///
314/// This pointer should be placed into the [`DroppingSlot`] passed into
315/// `deref_move`, so that it has a fixed lifetime for the duration of the frame
316/// that the [`MoveRef`] will exist for. The [`DroppingSlot`] will also provide
317/// a drop flag to use to build the returned [`MoveRef`].
318///
319/// The mutable reference returned by the [`DroppingSlot`] should then be
320/// converted into a [`MoveRef`]. The end result is that the [`DroppingSlot`]
321/// owns the "outer" part of the pointer, while the [`MoveRef`] owns the "inner"
322/// part. The `'frame` lifetime enforces the correct destruction order of these
323/// two parts, since the [`MoveRef`] borrows the [`DroppingSlot`].
324///
325/// The [`moveit!()`] macro helps by constructing the [`DroppingSlot`] for you.
326///
327/// ## Worked Example: [`Box<T>`]
328///
329/// To inhibit the inner destructor of [`Box<T>`], we can use `Box<MaybeUninit<T>>`
330/// as [`AsMove::Storage`]. [`MaybeUninit`] is preferred over [`ManuallyDrop`],
331/// since it helps avoid otherwise scary aliasing problems with `Box<&mut T>`.
332///
333/// The first step is to "cast" `Box<T>` into `Box<MaybeUninit<T>>` via
334/// [`Box::into_raw()`] and [`Box::from_raw()`]. This is then placed into the
335/// final storage location using [`DroppingSlot::put()`].
336///
337/// This returns a `&mut Box<MaybeUninit<T>>` and a [`DropFlag`]; the former is
338/// converted into an `&mut T` via [`MaybeUninit::assume_init_mut()`].
339///
340/// Finally, [`MoveRef::new_unchecked()`] is used to combine these into the
341/// return value.
342///
343/// The first step is safe because we construct a `MoveRef` to reinstate the
344/// destructor at the end of the function. The second step is safe because
345/// we know, a priori, that the `Box` contains an initialized value. The final
346/// step is safe, because we know, a priori, that the `Box` owns its pointee.
347///
348/// The use of the drop flag in this way makes it so that dropping the resulting
349/// `MoveRef` will leak the storage on the heap, exactly the same way as if we
350/// had leaked a `Box`.
351///
352/// ## Worked Example: [`MoveRef<T>`]
353///
354/// We don't need to inhibit any destructors: we just need to convert a
355/// `MoveRef<MoveRef<T>>` into a `MoveRef<T>`, which we can do by using
356/// [`MoveRef::into_inner()`]. [`AsMove::Storage`] can be whatever, so we
357/// simply choose [`()`] for this; the choice is arbitrary.
358///
359/// # Safety
360///
361/// Implementing `DerefMove` correctly requires that the uniqueness requirement
362/// of [`MoveRef`] is upheld. In particular, the following function *must not*
363/// violate memory safety:
364/// ```
365/// # use moveit::{DerefMove, MoveRef, moveit};
366/// fn move_out_of<P>(p: P) -> P::Target
367/// where
368///   P: DerefMove,
369///   P::Target: Sized,
370/// {
371///   unsafe {
372///     // Replace `p` with a move reference into it.
373///     moveit!(let p = &move *p);
374///     
375///     // Move out of `p`. From this point on, the `P::Target` destructor must
376///     // run when, and only when, the function's return value goes out of
377///     // scope per the usual Rust rules.
378///     //
379///     // In particular, the original `p` or any pointer it came from must not
380///     // run the destructor when they go out of scope, under any circumstance.
381///     MoveRef::into_inner(p)
382///   }
383/// }
384/// ```
385///
386/// `deref_move()` must also be `Pin`-safe; even though it does not accept a
387/// pinned reference, it must take care to not move its contents at any time.
388/// In particular, the implementation of [`AsMove::as_move()`] must be safe by
389/// definition.
390pub unsafe trait DerefMove: DerefMut + AsMove {
391  /// Moves out of `self`, producing a [`MoveRef`] that owns its contents.
392  ///
393  /// `storage` is a location *somewhere* responsible for rooting the lifetime
394  /// of `*this`'s storage. The location is unimportant, so long as it outlives
395  /// the resulting [`MoveRef`], which is enforced by the type signature.
396  ///
397  /// [`moveit!()`] provides a convenient syntax for calling this function.
398  fn deref_move<'frame>(
399    self,
400    storage: DroppingSlot<'frame, Self::Storage>,
401  ) -> MoveRef<'frame, Self::Target>
402  where
403    Self: 'frame;
404}
405
406unsafe impl<'a, T: ?Sized> DerefMove for MoveRef<'a, T> {
407  #[inline]
408  fn deref_move<'frame>(
409    self,
410    _storage: DroppingSlot<'frame, Self::Storage>,
411  ) -> MoveRef<'frame, Self::Target>
412  where
413    Self: 'frame,
414  {
415    self
416  }
417}
418
419/// Note that `DerefMove` cannot be used to move out of a `Pin<P>` when `P::Target: !Unpin`.
420/// ```compile_fail
421/// # use crate::{moveit::{Emplace, MoveRef, moveit}};
422/// # use core::{marker::PhantomPinned, pin::Pin};
423/// // Fails to compile because `Box<PhantomPinned>: Deref<Target = PhantomPinned>` and `PhantomPinned: !Unpin`.
424/// let ptr: Pin<Box<PhantomPinned>> = Box::emplace(moveit::new::default::<PhantomPinned>());
425/// moveit!(let mref = &move *ptr);
426///
427/// // Fails to compile because `MoveRef<PhantomPinned>: Deref<Target = PhantomPinned>` and `PhantomPinned: !Unpin`.
428/// moveit! {
429///   let mref0: Pin<MoveRef<PhantomPinned>> = moveit::new::default::<PhantomPinned>();
430///   let mref1 = &move *mref0;
431/// }
432unsafe impl<P> DerefMove for Pin<P>
433where
434  P: DerefMove, // needed for `AsMove: Pin<P>` for the call to `Self::as_move`
435  P::Target: Unpin, // needed for the call to `Pin::into_inner`
436{
437  #[inline]
438  fn deref_move<'frame>(
439    self,
440    storage: DroppingSlot<'frame, Self::Storage>,
441  ) -> MoveRef<'frame, Self::Target>
442  where
443    Self: 'frame,
444  {
445    Pin::into_inner(self.as_move(storage))
446  }
447}
448
449#[doc(hidden)]
450pub mod __macro {
451  use super::*;
452  use core::marker::PhantomData;
453
454  /// Type-inference helper for `moveit!`.
455  pub struct DerefPhantom<T>(PhantomData<*const T>);
456  impl<T: DerefMove> DerefPhantom<T> {
457    #[inline]
458    pub fn new(_: &T) -> Self {
459      Self(PhantomData)
460    }
461
462    #[inline]
463    pub fn deref_move<'frame>(
464      self,
465      this: T,
466      storage: DroppingSlot<'frame, T::Storage>,
467    ) -> MoveRef<'frame, T::Target>
468    where
469      Self: 'frame,
470    {
471      T::deref_move(this, storage)
472    }
473  }
474}
475
476/// Performs an emplacement operation.
477///
478/// This macro allows for three exotic types of `let` bindings:
479/// ```
480/// # use moveit::{moveit, new, move_ref::MoveRef};
481/// # use core::pin::Pin;
482/// let bx = Box::new(42);
483///
484/// moveit! {
485///   // Use a `New` to construct a new value in place on the stack. This
486///   // produces a value of type `Pin<MoveRef<_>>`.
487///   let x = new::default::<i32>();
488///   
489///   // Move out of an existing `DerefMove` type, such as a `Box`. This has
490///   // type `MoveRef<_>`, but can be pinned using `MoveRef::into_pin()`.
491///   let y = &move *bx;
492///   
493///   // Create a `MoveRef` of an existing type on the stack. This also has
494///   // type `MoveRef<_>`.
495///   let z = &move y;
496/// }
497/// ```
498///
499/// All three `lets`, including in-place construction, pin to the stack.
500/// Consider using something like [`Box::emplace()`] to perform construction on
501/// the heap.
502///
503/// This macro also has *temporary* forms, where rather than creating a binding,
504/// a temporary (which cannot outlive its complete expression) is created:
505///
506/// ```
507/// # use moveit::{moveit, new, move_ref::MoveRef};
508/// # use core::pin::Pin;
509/// fn do_thing(x: Pin<MoveRef<i32>>) {
510///   // ...
511/// # let _ = x;
512/// }
513///
514/// do_thing(moveit!(new::of(42)));
515/// ```
516///
517/// Note that these bindings cannot outlive the subexpression:
518/// ```compile_fail
519/// # use moveit::{moveit, new};
520/// let x = moveit!(new::of(42));
521/// let y = *x;  // Borrow checker error.
522/// ```
523///
524/// [`Box::emplace()`]: crate::new::Emplace::emplace
525#[macro_export]
526macro_rules! moveit {
527  (let $name:ident $(: $ty:ty)? = &move *$expr:expr $(; $($rest:tt)*)?) => {
528    $crate::moveit!(@move $name, $($ty)?, $expr);
529    $crate::moveit!($($($rest)*)?);
530  };
531  (let mut $name:ident $(: $ty:ty)? = &move *$expr:expr $(; $($rest:tt)*)?) => {
532    $crate::moveit!(@move(mut) $name, $($ty)?, $expr);
533    $crate::moveit!($($($rest)*)?);
534  };
535  (let $name:ident $(: $ty:ty)? = &move $expr:expr $(; $($rest:tt)*)?) => {
536    $crate::moveit!(@put $name, $($ty)?, $expr);
537    $crate::moveit!($($($rest)*)?);
538  };
539  (let mut $name:ident $(: $ty:ty)? = &move $expr:expr $(; $($rest:tt)*)?) => {
540    $crate::emplace!(@put(mut) $name, $($ty)?, $expr);
541    $crate::emplace!($($($rest)*)?);
542  };
543  (let $name:ident $(: $ty:ty)? = $expr:expr $(; $($rest:tt)*)?) => {
544    $crate::moveit!(@emplace $name, $($ty)?, $expr);
545    $crate::moveit!($($($rest)*)?);
546  };
547  (let mut $name:ident $(: $ty:ty)? = $expr:expr $(; $($rest:tt)*)?) => {
548    $crate::moveit!(@emplace(mut) $name, $($ty)?, $expr);
549    $crate::moveit!($($($rest)*)?);
550  };
551  ($(;)?) => {};
552
553  (&move *$expr:expr) => {
554    $crate::move_ref::DerefMove::deref_move(
555      $expr, $crate::slot!(#[dropping]),
556    )
557  };
558
559  (&move $expr:expr) => {$crate::slot!().put($expr)};
560  ($expr:expr) => {$crate::slot!().emplace($expr)};
561
562  (@move $(($mut:tt))? $name:ident, $($ty:ty)?, $expr:expr) => {
563    $crate::slot!(#[dropping] storage);
564
565    #[allow(unused_mut)]
566    let $($mut)? $name $(: $ty)? = $crate::move_ref::DerefMove::deref_move($expr, storage);
567  };
568  (@put $(($mut:tt))? $name:ident, $($ty:ty)?, $expr:expr) => {
569    $crate::slot!(slot);
570    let $($mut)? $name $(: $ty)? = slot.put($expr);
571  };
572  (@emplace $(($mut:tt))? $name:ident, $($ty:ty)?, $expr:expr) => {
573    $crate::slot!(slot);
574    let $($mut)? $name $(: $ty)? = slot.emplace($expr);
575  };
576}
577
578#[cfg(test)]
579pub(crate) mod test {
580  use crate::new;
581  use crate::MoveNew;
582  use crate::New;
583
584  use super::*;
585  use std::alloc;
586  use std::alloc::Layout;
587  use std::marker::PhantomPinned;
588  use std::mem::MaybeUninit;
589
590  #[test]
591  fn deref_move_of_move_ref() {
592    moveit! {
593      let x: MoveRef<Box<i32>> = &move Box::new(5);
594      let y: MoveRef<Box<i32>> = &move *x;
595    }
596    let _ = y;
597  }
598
599  #[test]
600  fn deref_move_of_box() {
601    let x = Box::new(5);
602    moveit!(let y: MoveRef<i32> = &move *x);
603    let _ = y;
604  }
605
606  #[test]
607  fn move_ref_into_inner() {
608    moveit!(let x: MoveRef<Box<i32>> = &move Box::new(5));
609    let _ = MoveRef::into_inner(x);
610  }
611
612  #[test]
613  #[should_panic]
614  fn unforgettable() {
615    moveit!(let x: MoveRef<i32> = &move 42);
616    mem::forget(x);
617  }
618
619  #[test]
620  #[should_panic]
621  fn unforgettable_temporary() {
622    mem::forget(moveit!(&move 42));
623  }
624
625  #[test]
626  fn forgettable_box() {
627    let mut x = Box::new(5);
628
629    // Save the pointer for later, so that we can free it to make Miri happy.
630    let ptr = x.as_mut() as *mut i32;
631
632    moveit!(let y: MoveRef<i32> = &move *x);
633
634    // This should leak but be otherwise safe.
635    mem::forget(y);
636
637    // Free the leaked pointer; Miri will notice if this turns out to be a
638    // double-free.
639    unsafe {
640      alloc::dealloc(ptr as *mut u8, Layout::new::<i32>());
641    }
642  }
643
644  #[test]
645  fn forgettable_box_temporary() {
646    let mut x = Box::new(5);
647
648    // Save the pointer for later, so that we can free it to make Miri happy.
649    let ptr = x.as_mut() as *mut i32;
650
651    // This should leak but be otherwise safe.
652    mem::forget(moveit!(&move *x));
653
654    // Free the leaked pointer; Miri will notice if this turns out to be a
655    // double-free.
656    unsafe {
657      alloc::dealloc(ptr as *mut u8, Layout::new::<i32>());
658    }
659  }
660
661  // This type is reused in test code in cxx_support.
662  #[derive(Default)]
663  pub(crate) struct Immovable {
664    _pin: PhantomPinned,
665  }
666
667  impl Immovable {
668    pub(crate) fn new() -> impl New<Output = Self> {
669      new::default()
670    }
671  }
672
673  unsafe impl MoveNew for Immovable {
674    unsafe fn move_new(
675      _src: Pin<MoveRef<Self>>,
676      _this: Pin<&mut MaybeUninit<Self>>,
677    ) {
678    }
679  }
680
681  #[test]
682  fn test_mov() {
683    moveit! {
684      let foo = Immovable::new();
685      let _foo = new::mov(foo);
686    }
687  }
688}