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 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
use crate::ops::{Deref, DerefMut}; use crate::ptr; /// 包装器,用于禁止编译器自动调用 T 的析构函数。 /// 该包装器的成本为 0。 /// /// `ManuallyDrop<T>` 与 `T` 进行相同的布局优化。 /// 因此,它在编译器对其内容进行假设的前提下具有 *no 效果*。 /// 例如,用 [`mem::zeroed`] 初始化 `ManuallyDrop<&mut T>` 是未定义的行为。 /// 如果需要处理未初始化的数据,请改用 [`MaybeUninit<T>`]。 /// /// 请注意,访问 `ManuallyDrop<T>` 内部的值是安全的。 /// 这意味着其内容已被丢弃的 `ManuallyDrop<T>` 一定不能通过公共安全 API 公开。 /// 相应地,`ManuallyDrop::drop` 是不安全的。 /// /// # `ManuallyDrop` 和 drop 指令。 /// /// Rust 具有定义明确的 [drop order] 值。 /// 为确保按特定顺序丢弃字段或局部变量,请对声明重新排序,以使隐式丢弃顺序正确。 /// /// 可以使用 `ManuallyDrop` 来控制丢弃顺序,但这需要不安全的代码,并且在展开状态下很难正确执行。 /// /// /// 例如,如果您想要确保一个特定的字段在其他字段之后被丢弃,将它作为结构的最后一个字段: /// /// ``` /// struct Context; /// /// struct Widget { /// children: Vec<Widget>, /// // `context` 将在 `children` 之后被丢弃。 /// // Rust 保证按声明顺序丢弃字段。 /// context: Context, /// } /// ``` /// /// [drop order]: https://doc.rust-lang.org/reference/destructors.html /// [`mem::zeroed`]: crate::mem::zeroed /// [`MaybeUninit<T>`]: crate::mem::MaybeUninit /// /// /// /// /// #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] pub struct ManuallyDrop<T: ?Sized> { value: T, } impl<T> ManuallyDrop<T> { /// 包装一个要手动丢弃的值。 /// /// # Examples /// /// ```rust /// use std::mem::ManuallyDrop; /// let mut x = ManuallyDrop::new(String::from("Hello World!")); /// x.truncate(5); // 您仍然可以安全地操作值 /// assert_eq!(*x, "Hello"); /// // 但是 `Drop` 不会在这里运行 /// ``` #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"] #[stable(feature = "manually_drop", since = "1.20.0")] #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] #[inline(always)] pub const fn new(value: T) -> ManuallyDrop<T> { ManuallyDrop { value } } /// 从 `ManuallyDrop` 容器中提取值。 /// /// 这样可以再次丢弃该值。 /// /// # Examples /// /// ```rust /// use std::mem::ManuallyDrop; /// let x = ManuallyDrop::new(Box::new(())); /// let _: Box<()> = ManuallyDrop::into_inner(x); // 这将使 `Box` 丢弃。 /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] #[inline(always)] pub const fn into_inner(slot: ManuallyDrop<T>) -> T { slot.value } /// 从 `ManuallyDrop<T>` 容器中取出值。 /// /// 此方法主要用于在 drop 中移出值。 /// 您可以使用此方法获取值并根据需要使用它,而不是使用 [`ManuallyDrop::drop`] 手动删除该值。 /// /// 只要有可能,最好改用 [`into_inner`][`ManuallyDrop::into_inner`],这样可以防止重复 `ManuallyDrop<T>` 的内容。 /// /// /// # Safety /// /// 该函数从语义上移出所包含的值,而不会阻止进一步使用,从而使该容器的状态保持不变。 /// 您有责任确保不再使用此 `ManuallyDrop`。 /// /// /// #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] #[stable(feature = "manually_drop_take", since = "1.42.0")] #[inline] pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T { // SAFETY: 我们正在从引文中进行读取,该引文保证对读取有效。 // unsafe { ptr::read(&slot.value) } } } impl<T: ?Sized> ManuallyDrop<T> { /// 手动丢弃包含的值。这完全等同于使用指向所包含值的指针来调用 [`ptr::drop_in_place`]。 /// 这样,除非所包含的值是包装的结构体,否则析构函数将在不移动值的情况下就地调用,因此可用于安全地丢弃 [pinned] 数据。 /// /// 如果您拥有该值的所有权,则可以改用 [`ManuallyDrop::into_inner`]。 /// /// # Safety /// /// 此函数运行包含值的析构函数。 /// 除了析构函数本身所做的更改之外,内存保持不变,因此就编译器而言,仍然保留一种对于 `T` 类型有效的位模式。 /// /// /// 但是,此 "zombie" 值不应暴露给安全代码,并且不应多次调用此函数。 /// 在丢弃值或多次丢弃值后使用该值可能会导致未定义行为 (取决于 `drop` 的作用)。 /// 类型系统通常会阻止这种情况,但是 `ManuallyDrop` 的用户必须坚持这些保证,而无需编译器的帮助。 /// /// [pinned]: crate::pin /// /// /// /// #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub unsafe fn drop(slot: &mut ManuallyDrop<T>) { // SAFETY: 我们将丢弃变量引用所指向的值,该值对于写操作是有效的。 // // 取决于调用者,以确保不会再次丢弃 `slot`。 unsafe { ptr::drop_in_place(&mut slot.value) } } } #[stable(feature = "manually_drop", since = "1.20.0")] impl<T: ?Sized> Deref for ManuallyDrop<T> { type Target = T; #[inline(always)] fn deref(&self) -> &T { &self.value } } #[stable(feature = "manually_drop", since = "1.20.0")] impl<T: ?Sized> DerefMut for ManuallyDrop<T> { #[inline(always)] fn deref_mut(&mut self) -> &mut T { &mut self.value } }