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 
46 use core::mem;
47 use core::ops::Deref;
48 use core::ops::DerefMut;
49 use core::pin::Pin;
50 use core::ptr;
51 
52 #[cfg(doc)]
53 use {
54   crate::{drop_flag, moveit},
55   alloc::{boxed::Box, rc::Rc, sync::Arc},
56   core::mem::{ManuallyDrop, MaybeUninit},
57 };
58 
59 use crate::drop_flag::DropFlag;
60 use 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.
66 pub struct MoveRef<'a, T: ?Sized> {
67   ptr: &'a mut T,
68   drop_flag: DropFlag<'a>,
69 }
70 
71 impl<'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]
new_unchecked(ptr: &'a mut T, drop_flag: DropFlag<'a>) -> Self87   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]
into_pin(this: Self) -> Pin<Self>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]
as_ptr(this: &Self) -> *const T105   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]
as_mut_ptr(this: &mut Self) -> *mut T114   pub fn as_mut_ptr(this: &mut Self) -> *mut T {
115     this.ptr
116   }
117 
118   #[allow(unused)]
drop_flag(this: &Self) -> DropFlag<'a>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.
125 impl<'a, T> MoveRef<'a, T> {
126   /// Consumes `self`, blindly casting the inner pointer to `U`.
cast<U>(mut self) -> MoveRef<'a, 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 
137 impl<'a, T> MoveRef<'a, T> {
138   /// Consume the `MoveRef<T>`, returning the wrapped value.
139   #[inline]
into_inner(this: Self) -> T140   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 
149 impl<T: ?Sized> Deref for MoveRef<'_, T> {
150   type Target = T;
151 
152   #[inline]
deref(&self) -> &Self::Target153   fn deref(&self) -> &Self::Target {
154     self.ptr
155   }
156 }
157 
158 impl<T: ?Sized> DerefMut for MoveRef<'_, T> {
159   #[inline]
deref_mut(&mut self) -> &mut Self::Target160   fn deref_mut(&mut self) -> &mut Self::Target {
161     self.ptr
162   }
163 }
164 
165 impl<T: ?Sized> Drop for MoveRef<'_, T> {
166   #[inline]
drop(&mut self)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 
173 impl<'a, T> From<MoveRef<'a, T>> for Pin<MoveRef<'a, T>> {
174   #[inline]
from(x: MoveRef<'a, T>) -> Self175   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`].
212 pub 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()`].
as_move<'frame>( self, storage: DroppingSlot<'frame, Self::Storage>, ) -> Pin<MoveRef<'frame, Self::Target>> where Self: 'frame231   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 
239 impl<'f, T: ?Sized> AsMove for MoveRef<'f, T> {
240   type Storage = ();
241 
242   #[inline]
as_move<'frame>( self, storage: DroppingSlot<'frame, Self::Storage>, ) -> Pin<MoveRef<'frame, Self::Target>> where Self: 'frame,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 
254 impl<P: DerefMove> AsMove for Pin<P> {
255   type Storage = P::Storage;
256 
257   #[inline]
as_move<'frame>( self, storage: DroppingSlot<'frame, Self::Storage>, ) -> Pin<MoveRef<'frame, Self::Target>> where Self: 'frame,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.
390 pub 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.
deref_move<'frame>( self, storage: DroppingSlot<'frame, Self::Storage>, ) -> MoveRef<'frame, Self::Target> where Self: 'frame398   fn deref_move<'frame>(
399     self,
400     storage: DroppingSlot<'frame, Self::Storage>,
401   ) -> MoveRef<'frame, Self::Target>
402   where
403     Self: 'frame;
404 }
405 
406 unsafe impl<'a, T: ?Sized> DerefMove for MoveRef<'a, T> {
407   #[inline]
deref_move<'frame>( self, _storage: DroppingSlot<'frame, Self::Storage>, ) -> MoveRef<'frame, Self::Target> where Self: 'frame,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 /// }
432 unsafe impl<P> DerefMove for Pin<P>
433 where
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]
deref_move<'frame>( self, storage: DroppingSlot<'frame, Self::Storage>, ) -> MoveRef<'frame, Self::Target> where Self: 'frame,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)]
450 pub 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]
new(_: &T) -> Self458     pub fn new(_: &T) -> Self {
459       Self(PhantomData)
460     }
461 
462     #[inline]
deref_move<'frame>( self, this: T, storage: DroppingSlot<'frame, T::Storage>, ) -> MoveRef<'frame, T::Target> where Self: 'frame,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]
526 macro_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)]
579 pub(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]
deref_move_of_move_ref()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]
deref_move_of_box()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]
move_ref_into_inner()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]
unforgettable()614   fn unforgettable() {
615     moveit!(let x: MoveRef<i32> = &move 42);
616     mem::forget(x);
617   }
618 
619   #[test]
620   #[should_panic]
unforgettable_temporary()621   fn unforgettable_temporary() {
622     mem::forget(moveit!(&move 42));
623   }
624 
625   #[test]
forgettable_box()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]
forgettable_box_temporary()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 {
new() -> impl New<Output = Self>668     pub(crate) fn new() -> impl New<Output = Self> {
669       new::default()
670     }
671   }
672 
673   unsafe impl MoveNew for Immovable {
move_new( _src: Pin<MoveRef<Self>>, _this: Pin<&mut MaybeUninit<Self>>, )674     unsafe fn move_new(
675       _src: Pin<MoveRef<Self>>,
676       _this: Pin<&mut MaybeUninit<Self>>,
677     ) {
678     }
679   }
680 
681   #[test]
test_mov()682   fn test_mov() {
683     moveit! {
684       let foo = Immovable::new();
685       let _foo = new::mov(foo);
686     }
687   }
688 }
689