core/mem/
manually_drop.rs

1use crate::ops::{Deref, DerefMut, DerefPure};
2use 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]
157pub struct ManuallyDrop<T: ?Sized> {
158    value: T,
159}
160
161impl<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
227impl<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")]
261impl<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")]
270impl<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")]
278unsafe impl<T: ?Sized> DerefPure for ManuallyDrop<T> {}