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