1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
use ::core::mem::ManuallyDrop; #[cfg(doc)] use crate::Out; /// Extension trait providing a cast to the [`ManuallyDrop`] type. /// /// This is useful if you want to use an [`Out`] reference to something that /// is not `Copy` (potentially because it has drop glue, in which case you /// either don't mind leaking / skipping that drop glue, or you know you will /// be manually handling it). /// /// ⚠️ **Misusage of this function can thus lead to memory leaks** ⚠️ /// /// # Example /// /// The following fails to compile because of the missing `Copy` bound: /// /// ```rust,compile_fail /// use ::uninit::prelude::*; /// use ::core::cell::Cell; /// /// let mut cell = Cell::new(0); /// cell.as_out().write(Cell::new(42)); // Error, not `Copy` /// assert_eq!(cell.get(), 42); /// ``` /// /// We see here that the `Copy` bound can be too restrictive. By calling /// `.manually_drop_mut()`, we no longer need to satisfy this `Copy` bound; but /// then we need to be careful with memory leaks. /// /// Since `::core::mem::needs_drop::<Cell<_>>() == false`, there is nothing to /// worry about: /// /// ```rust /// use ::uninit::prelude::*; /// use ::core::cell::Cell; /// /// let mut cell = Cell::new(0); /// cell.manually_drop_mut().as_out().write(Cell::new(42)); // OK /// assert_eq!(cell.get(), 42); /// ``` /// /// # Counterexample /// /// ```rust /// use ::uninit::prelude::*; /// use ::std::rc::Rc; /// /// let rc = Rc::new(()); /// assert_eq!(Rc::strong_count(&rc), 1); /// let mut rc2 = Some(Rc::clone(&rc)); /// assert_eq!(Rc::strong_count(&rc), 2); /// // This overwrites `rc2` without running any destructor whatsoever, hence /// // leaking the `rc` clone. /// rc2.manually_drop_mut().as_out().write(None); /// assert_eq!(Rc::strong_count(&rc), 2); /// assert!(Rc::try_unwrap(rc).is_err()); /// ``` #[allow(missing_docs)] pub trait ManuallyDropMut { type Ret : ?Sized; fn manually_drop_mut (self: &'_ mut Self) -> &'_ mut Self::Ret ; } impl<T> ManuallyDropMut for [T] { type Ret = [ManuallyDrop<T>]; #[inline] fn manually_drop_mut<'__> (self: &'__ mut [T]) -> &'__ mut [ManuallyDrop<T>] { let len = self.len(); unsafe { // Safety: `ManuallyDrop<T>` is `#[repr(transparent)]` ::core::slice::from_raw_parts_mut( self.as_mut_ptr().cast(), len, ) } } } impl<T> ManuallyDropMut for T { type Ret = ManuallyDrop<T>; #[inline] fn manually_drop_mut<'__> (self: &'__ mut T) -> &'__ mut ManuallyDrop<T> { unsafe { // Safety: `ManuallyDrop<T>` is `#[repr(transparent)]` ::core::mem::transmute(self) } } }