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