1 | use crate::ops::{Deref, DerefMut, DerefPure}; |
2 | use crate::ptr; |
3 | |
4 | /// A wrapper to inhibit the compiler from automatically calling `T`’s |
5 | /// destructor. This wrapper is 0-cost. |
6 | /// |
7 | /// `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as |
8 | /// `T`, and is subject to the same layout optimizations as `T`. As a |
9 | /// consequence, it has *no effect* on the assumptions that the compiler makes |
10 | /// about its contents. For example, initializing a `ManuallyDrop<&mut T>` with |
11 | /// [`mem::zeroed`] is undefined behavior. If you need to handle uninitialized |
12 | /// data, use [`MaybeUninit<T>`] instead. |
13 | /// |
14 | /// Note that accessing the value inside a `ManuallyDrop<T>` is safe. This means |
15 | /// that a `ManuallyDrop<T>` whose content has been dropped must not be exposed |
16 | /// through a public safe API. Correspondingly, `ManuallyDrop::drop` is unsafe. |
17 | /// |
18 | /// # `ManuallyDrop` and drop order |
19 | /// |
20 | /// Rust has a well-defined [drop order] of values. To make sure that fields or |
21 | /// locals are dropped in a specific order, reorder the declarations such that |
22 | /// the implicit drop order is the correct one. |
23 | /// |
24 | /// It is possible to use `ManuallyDrop` to control the drop order, but this |
25 | /// requires unsafe code and is hard to do correctly in the presence of |
26 | /// unwinding. |
27 | /// |
28 | /// For example, if you want to make sure that a specific field is dropped after |
29 | /// the others, make it the last field of a struct: |
30 | /// |
31 | /// ``` |
32 | /// struct Context; |
33 | /// |
34 | /// struct Widget { |
35 | /// children: Vec<Widget>, |
36 | /// // `context` will be dropped after `children`. |
37 | /// // Rust guarantees that fields are dropped in the order of declaration. |
38 | /// context: Context, |
39 | /// } |
40 | /// ``` |
41 | /// |
42 | /// # Interaction with `Box` |
43 | /// |
44 | /// Currently, if you have a `ManuallyDrop<T>`, where the type `T` is a `Box` or |
45 | /// contains a `Box` inside, then dropping the `T` followed by moving the |
46 | /// `ManuallyDrop<T>` is [considered to be undefined |
47 | /// behavior](https://github.com/rust-lang/unsafe-code-guidelines/issues/245). |
48 | /// That is, the following code causes undefined behavior: |
49 | /// |
50 | /// ```no_run |
51 | /// use std::mem::ManuallyDrop; |
52 | /// |
53 | /// let mut x = ManuallyDrop::new(Box::new(42)); |
54 | /// unsafe { |
55 | /// ManuallyDrop::drop(&mut x); |
56 | /// } |
57 | /// let y = x; // Undefined behavior! |
58 | /// ``` |
59 | /// |
60 | /// This is [likely to change in the |
61 | /// future](https://rust-lang.github.io/rfcs/3336-maybe-dangling.html). In the |
62 | /// meantime, consider using [`MaybeUninit`] instead. |
63 | /// |
64 | /// # Safety hazards when storing `ManuallyDrop` in a struct or an enum. |
65 | /// |
66 | /// Special care is needed when all of the conditions below are met: |
67 | /// * A struct or enum contains a `ManuallyDrop`. |
68 | /// * The `ManuallyDrop` is not inside a `union`. |
69 | /// * The struct or enum is part of public API, or is stored in a struct or an |
70 | /// enum that is part of public API. |
71 | /// * There is code that drops the contents of the `ManuallyDrop` field, and |
72 | /// this code is outside the struct or enum's `Drop` implementation. |
73 | /// |
74 | /// In particular, the following hazards may occur: |
75 | /// |
76 | /// #### Storing generic types |
77 | /// |
78 | /// If the `ManuallyDrop` contains a client-supplied generic type, the client |
79 | /// might provide a `Box` as that type. This would cause undefined behavior when |
80 | /// the struct or enum is later moved, as mentioned in the previous section. For |
81 | /// example, the following code causes undefined behavior: |
82 | /// |
83 | /// ```no_run |
84 | /// use std::mem::ManuallyDrop; |
85 | /// |
86 | /// pub struct BadOption<T> { |
87 | /// // Invariant: Has been dropped iff `is_some` is false. |
88 | /// value: ManuallyDrop<T>, |
89 | /// is_some: bool, |
90 | /// } |
91 | /// impl<T> BadOption<T> { |
92 | /// pub fn new(value: T) -> Self { |
93 | /// Self { value: ManuallyDrop::new(value), is_some: true } |
94 | /// } |
95 | /// pub fn change_to_none(&mut self) { |
96 | /// if self.is_some { |
97 | /// self.is_some = false; |
98 | /// unsafe { |
99 | /// // SAFETY: `value` hasn't been dropped yet, as per the invariant |
100 | /// // (This is actually unsound!) |
101 | /// ManuallyDrop::drop(&mut self.value); |
102 | /// } |
103 | /// } |
104 | /// } |
105 | /// } |
106 | /// |
107 | /// // In another crate: |
108 | /// |
109 | /// let mut option = BadOption::new(Box::new(42)); |
110 | /// option.change_to_none(); |
111 | /// let option2 = option; // Undefined behavior! |
112 | /// ``` |
113 | /// |
114 | /// #### Deriving traits |
115 | /// |
116 | /// Deriving `Debug`, `Clone`, `PartialEq`, `PartialOrd`, `Ord`, or `Hash` on |
117 | /// the struct or enum could be unsound, since the derived implementations of |
118 | /// these traits would access the `ManuallyDrop` field. For example, the |
119 | /// following code causes undefined behavior: |
120 | /// |
121 | /// ```no_run |
122 | /// use std::mem::ManuallyDrop; |
123 | /// |
124 | /// // This derive is unsound in combination with the `ManuallyDrop::drop` call. |
125 | /// #[derive(Debug)] |
126 | /// pub struct Foo { |
127 | /// value: ManuallyDrop<String>, |
128 | /// } |
129 | /// impl Foo { |
130 | /// pub fn new() -> Self { |
131 | /// let mut temp = Self { |
132 | /// value: ManuallyDrop::new(String::from("Unsafe rust is hard." )) |
133 | /// }; |
134 | /// unsafe { |
135 | /// // SAFETY: `value` hasn't been dropped yet. |
136 | /// ManuallyDrop::drop(&mut temp.value); |
137 | /// } |
138 | /// temp |
139 | /// } |
140 | /// } |
141 | /// |
142 | /// // In another crate: |
143 | /// |
144 | /// let foo = Foo::new(); |
145 | /// println!("{:?}" , foo); // Undefined behavior! |
146 | /// ``` |
147 | /// |
148 | /// [drop order]: https://doc.rust-lang.org/reference/destructors.html |
149 | /// [`mem::zeroed`]: crate::mem::zeroed |
150 | /// [`MaybeUninit<T>`]: crate::mem::MaybeUninit |
151 | /// [`MaybeUninit`]: crate::mem::MaybeUninit |
152 | #[stable (feature = "manually_drop" , since = "1.20.0" )] |
153 | #[lang = "manually_drop" ] |
154 | #[derive (Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] |
155 | #[repr (transparent)] |
156 | #[rustc_pub_transparent] |
157 | pub struct ManuallyDrop<T: ?Sized> { |
158 | value: T, |
159 | } |
160 | |
161 | impl<T> ManuallyDrop<T> { |
162 | /// Wrap a value to be manually dropped. |
163 | /// |
164 | /// # Examples |
165 | /// |
166 | /// ```rust |
167 | /// use std::mem::ManuallyDrop; |
168 | /// let mut x = ManuallyDrop::new(String::from("Hello World!" )); |
169 | /// x.truncate(5); // You can still safely operate on the value |
170 | /// assert_eq!(*x, "Hello" ); |
171 | /// // But `Drop` will not be run here |
172 | /// # // FIXME(https://github.com/rust-lang/miri/issues/3670): |
173 | /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak. |
174 | /// # let _ = ManuallyDrop::into_inner(x); |
175 | /// ``` |
176 | #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead" ] |
177 | #[stable (feature = "manually_drop" , since = "1.20.0" )] |
178 | #[rustc_const_stable (feature = "const_manually_drop" , since = "1.32.0" )] |
179 | #[inline (always)] |
180 | pub const fn new(value: T) -> ManuallyDrop<T> { |
181 | ManuallyDrop { value } |
182 | } |
183 | |
184 | /// Extracts the value from the `ManuallyDrop` container. |
185 | /// |
186 | /// This allows the value to be dropped again. |
187 | /// |
188 | /// # Examples |
189 | /// |
190 | /// ```rust |
191 | /// use std::mem::ManuallyDrop; |
192 | /// let x = ManuallyDrop::new(Box::new(())); |
193 | /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. |
194 | /// ``` |
195 | #[stable (feature = "manually_drop" , since = "1.20.0" )] |
196 | #[rustc_const_stable (feature = "const_manually_drop" , since = "1.32.0" )] |
197 | #[inline (always)] |
198 | pub const fn into_inner(slot: ManuallyDrop<T>) -> T { |
199 | slot.value |
200 | } |
201 | |
202 | /// Takes the value from the `ManuallyDrop<T>` container out. |
203 | /// |
204 | /// This method is primarily intended for moving out values in drop. |
205 | /// Instead of using [`ManuallyDrop::drop`] to manually drop the value, |
206 | /// you can use this method to take the value and use it however desired. |
207 | /// |
208 | /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`] |
209 | /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`. |
210 | /// |
211 | /// # Safety |
212 | /// |
213 | /// This function semantically moves out the contained value without preventing further usage, |
214 | /// leaving the state of this container unchanged. |
215 | /// It is your responsibility to ensure that this `ManuallyDrop` is not used again. |
216 | /// |
217 | #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead" ] |
218 | #[stable (feature = "manually_drop_take" , since = "1.42.0" )] |
219 | #[inline ] |
220 | pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T { |
221 | // SAFETY: we are reading from a reference, which is guaranteed |
222 | // to be valid for reads. |
223 | unsafe { ptr::read(&slot.value) } |
224 | } |
225 | } |
226 | |
227 | impl<T: ?Sized> ManuallyDrop<T> { |
228 | /// Manually drops the contained value. |
229 | /// |
230 | /// This is exactly equivalent to calling [`ptr::drop_in_place`] with a |
231 | /// pointer to the contained value. As such, unless the contained value is a |
232 | /// packed struct, the destructor will be called in-place without moving the |
233 | /// value, and thus can be used to safely drop [pinned] data. |
234 | /// |
235 | /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead. |
236 | /// |
237 | /// # Safety |
238 | /// |
239 | /// This function runs the destructor of the contained value. Other than changes made by |
240 | /// the destructor itself, the memory is left unchanged, and so as far as the compiler is |
241 | /// concerned still holds a bit-pattern which is valid for the type `T`. |
242 | /// |
243 | /// However, this "zombie" value should not be exposed to safe code, and this function |
244 | /// should not be called more than once. To use a value after it's been dropped, or drop |
245 | /// a value multiple times, can cause Undefined Behavior (depending on what `drop` does). |
246 | /// This is normally prevented by the type system, but users of `ManuallyDrop` must |
247 | /// uphold those guarantees without assistance from the compiler. |
248 | /// |
249 | /// [pinned]: crate::pin |
250 | #[stable (feature = "manually_drop" , since = "1.20.0" )] |
251 | #[inline ] |
252 | pub unsafe fn drop(slot: &mut ManuallyDrop<T>) { |
253 | // SAFETY: we are dropping the value pointed to by a mutable reference |
254 | // which is guaranteed to be valid for writes. |
255 | // It is up to the caller to make sure that `slot` isn't dropped again. |
256 | unsafe { ptr::drop_in_place(&mut slot.value) } |
257 | } |
258 | } |
259 | |
260 | #[stable (feature = "manually_drop" , since = "1.20.0" )] |
261 | impl<T: ?Sized> Deref for ManuallyDrop<T> { |
262 | type Target = T; |
263 | #[inline (always)] |
264 | fn deref(&self) -> &T { |
265 | &self.value |
266 | } |
267 | } |
268 | |
269 | #[stable (feature = "manually_drop" , since = "1.20.0" )] |
270 | impl<T: ?Sized> DerefMut for ManuallyDrop<T> { |
271 | #[inline (always)] |
272 | fn deref_mut(&mut self) -> &mut T { |
273 | &mut self.value |
274 | } |
275 | } |
276 | |
277 | #[unstable (feature = "deref_pure_trait" , issue = "87121" )] |
278 | unsafe impl<T: ?Sized> DerefPure for ManuallyDrop<T> {} |
279 | |