core/mem/
manually_drop.rs

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