Skip to main content

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/// # Safety hazards when storing `ManuallyDrop` in a struct or an enum.
47///
48/// Special care is needed when all of the conditions below are met:
49/// * A struct or enum contains a `ManuallyDrop`.
50/// * The `ManuallyDrop` is not inside a `union`.
51/// * The struct or enum is part of public API, or is stored in a struct or an
52///   enum that is part of public API.
53/// * There is a _safe_ function that drops the contents of the `ManuallyDrop`
54///   field, and it can be called outside the struct or enum's `Drop` implementation.
55///
56/// In particular, deriving `Debug`, `Clone`, `PartialEq`, `PartialOrd`, `Ord`,
57/// or `Hash` on the struct or enum could be unsound, since the derived
58/// implementations of these traits would access the `ManuallyDrop` field.
59///
60/// For example, in the following code, `derive(Debug)` is unsound in combination
61/// with the `ManuallyDrop::drop` call in `Foo::new`:
62///
63/// ```no_run
64/// # use std::mem::ManuallyDrop;
65/// #[derive(Debug)]
66/// pub struct Foo {
67///     /// Invariant: this value may have been dropped!
68///     value: ManuallyDrop<String>,
69/// }
70/// impl Foo {
71///     pub fn new() -> Self {
72///         let mut temp = Self {
73///             value: ManuallyDrop::new(String::from("Unsafe rust is hard."))
74///         };
75///         unsafe {
76///             // SAFETY: `value` hasn't been dropped yet.
77///             ManuallyDrop::drop(&mut temp.value);
78///         }
79///         temp
80///     }
81/// }
82/// ```
83///
84/// As one could use the `Debug` implementation to access an already dropped
85/// field:
86///
87/// ```rust,ignore (uses-type-from-separate-snippet)
88/// let foo = Foo::new();
89/// println!("{foo:?}"); // Undefined behavior!
90/// ```
91///
92/// Note that similar unsoundness can arise without `derive`. The cause of the
93/// unsoundness are public APIs which allow to access an already dropped value
94/// inside `ManuallyDrop`.
95///
96/// # Pre-`1.96` Interaction with `Box`
97///
98/// Before Rust `1.96.0`, if you had a `ManuallyDrop<T>`, where the type `T`
99/// was a `Box` or contained a `Box` inside, then dropping the `T` followed by
100/// moving the `ManuallyDrop<T>` was [considered to be undefined
101/// behavior](https://github.com/rust-lang/unsafe-code-guidelines/issues/245).
102/// That is, the following code caused undefined behavior:
103///
104/// ```no_run
105/// use std::mem::ManuallyDrop;
106///
107/// let mut x = ManuallyDrop::new(Box::new(42));
108/// unsafe {
109///     ManuallyDrop::drop(&mut x);
110/// }
111/// let y = x; // Undefined behavior! (pre 1.96.0)
112/// ```
113///
114/// Note that this could also have happen with a generic type where the user of
115/// the library providing it could substitute the generic for a `Box<_>` and
116/// then move the library type:
117///
118/// ```no_run
119/// use std::mem::ManuallyDrop;
120///
121/// pub struct BadOption<T> {
122///     // Invariant: Has been dropped if `is_some` is false.
123///     value: ManuallyDrop<T>,
124///     is_some: bool,
125/// }
126/// impl<T> BadOption<T> {
127///     pub fn new(value: T) -> Self {
128///         Self { value: ManuallyDrop::new(value), is_some: true }
129///     }
130///     pub fn change_to_none(&mut self) {
131///         if self.is_some {
132///             self.is_some = false;
133///             unsafe {
134///                 // SAFETY: `value` hasn't been dropped yet, as per the invariant
135///                 // (This is actually unsound pre rust 1.96.0!)
136///                 ManuallyDrop::drop(&mut self.value);
137///             }
138///         }
139///     }
140/// }
141///
142/// // In another crate:
143///
144/// let mut option = BadOption::new(Box::new(42));
145/// option.change_to_none();
146/// let option2 = option; // Undefined behavior! (pre 1.96)
147/// ```
148///
149/// [drop order]: https://doc.rust-lang.org/reference/destructors.html
150/// [`mem::zeroed`]: crate::mem::zeroed
151/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
152/// [`MaybeUninit`]: crate::mem::MaybeUninit
153#[stable(feature = "manually_drop", since = "1.20.0")]
154#[lang = "manually_drop"]
155#[derive(#[automatically_derived]
#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: crate::marker::Copy + ?Sized> crate::marker::Copy for ManuallyDrop<T>
    {
}Copy, #[automatically_derived]
#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: crate::clone::Clone + ?Sized> crate::clone::Clone for ManuallyDrop<T>
    {
    #[inline]
    fn clone(&self) -> ManuallyDrop<T> {
        ManuallyDrop { value: crate::clone::Clone::clone(&self.value) }
    }
}Clone, #[automatically_derived]
#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: crate::fmt::Debug + ?Sized> crate::fmt::Debug for ManuallyDrop<T> {
    #[inline]
    fn fmt(&self, f: &mut crate::fmt::Formatter) -> crate::fmt::Result {
        crate::fmt::Formatter::debug_struct_field1_finish(f, "ManuallyDrop",
            "value", &&self.value)
    }
}Debug, #[automatically_derived]
#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: crate::default::Default + ?Sized> crate::default::Default for
    ManuallyDrop<T> {
    #[inline]
    fn default() -> ManuallyDrop<T> {
        ManuallyDrop { value: crate::default::Default::default() }
    }
}Default)]
156#[repr(transparent)]
157#[rustc_pub_transparent]
158pub struct ManuallyDrop<T: ?Sized> {
159    value: MaybeDangling<T>,
160}
161
162impl<T> ManuallyDrop<T> {
163    /// Wrap a value to be manually dropped.
164    ///
165    /// # Examples
166    ///
167    /// ```rust
168    /// use std::mem::ManuallyDrop;
169    /// let mut x = ManuallyDrop::new(String::from("Hello World!"));
170    /// x.truncate(5); // You can still safely operate on the value
171    /// assert_eq!(*x, "Hello");
172    /// // But `Drop` will not be run here
173    /// # // FIXME(https://github.com/rust-lang/miri/issues/3670):
174    /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak.
175    /// # let _ = ManuallyDrop::into_inner(x);
176    /// ```
177    #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"]
178    #[stable(feature = "manually_drop", since = "1.20.0")]
179    #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")]
180    #[inline(always)]
181    #[rustc_no_writable]
182    pub const fn new(value: T) -> ManuallyDrop<T> {
183        ManuallyDrop { value: MaybeDangling::new(value) }
184    }
185
186    /// Extracts the value from the `ManuallyDrop` container.
187    ///
188    /// This allows the value to be dropped again.
189    ///
190    /// # Examples
191    ///
192    /// ```rust
193    /// use std::mem::ManuallyDrop;
194    /// let x = ManuallyDrop::new(Box::new(()));
195    /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
196    /// ```
197    #[stable(feature = "manually_drop", since = "1.20.0")]
198    #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")]
199    #[inline(always)]
200    pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
201        // Cannot use `MaybeDangling::into_inner` as that does not yet have the desired semantics.
202        // SAFETY: We know this is a valid `T`. `slot` will not be dropped.
203        unsafe { (&raw const slot).cast::<T>().read() }
204    }
205
206    /// Takes the value from the `ManuallyDrop<T>` container out.
207    ///
208    /// This method is primarily intended for moving out values in drop.
209    /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
210    /// you can use this method to take the value and use it however desired.
211    ///
212    /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`]
213    /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`.
214    ///
215    /// # Safety
216    ///
217    /// This function semantically moves out the contained value without preventing further usage,
218    /// leaving the state of this container unchanged.
219    /// It is your responsibility to ensure that this `ManuallyDrop` is not used again.
220    ///
221    #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
222    #[stable(feature = "manually_drop_take", since = "1.42.0")]
223    #[rustc_const_unstable(feature = "const_manually_drop_take", issue = "148773")]
224    #[inline]
225    pub const unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
226        // SAFETY: we are reading from a reference, which is guaranteed
227        // to be valid for reads.
228        unsafe { ptr::read(slot.value.as_ref()) }
229    }
230}
231
232impl<T: ?Sized> ManuallyDrop<T> {
233    /// Manually drops the contained value.
234    ///
235    /// This is exactly equivalent to calling [`ptr::drop_in_place`] with a
236    /// pointer to the contained value. As such, unless the contained value is a
237    /// packed struct, the destructor will be called in-place without moving the
238    /// value, and thus can be used to safely drop [pinned] data.
239    ///
240    /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
241    ///
242    /// # Safety
243    ///
244    /// This function runs the destructor of the contained value. Other than changes made by
245    /// the destructor itself, the memory is left unchanged, and so as far as the compiler is
246    /// concerned still holds a bit-pattern which is valid for the type `T`.
247    ///
248    /// However, this "zombie" value should not be exposed to safe code, and this function
249    /// should not be called more than once. To use a value after it's been dropped, or drop
250    /// a value multiple times, can cause Undefined Behavior (depending on what `drop` does).
251    /// This is normally prevented by the type system, but users of `ManuallyDrop` must
252    /// uphold those guarantees without assistance from the compiler.
253    ///
254    /// [pinned]: crate::pin
255    #[stable(feature = "manually_drop", since = "1.20.0")]
256    #[inline]
257    #[rustc_const_unstable(feature = "const_drop_in_place", issue = "109342")]
258    pub const unsafe fn drop(slot: &mut ManuallyDrop<T>)
259    where
260        T: [const] Destruct,
261    {
262        // SAFETY: we are dropping the value pointed to by a mutable reference
263        // which is guaranteed to be valid for writes.
264        // It is up to the caller to make sure that `slot` isn't dropped again.
265        unsafe { ptr::drop_in_place(slot.value.as_mut()) }
266    }
267}
268
269#[stable(feature = "manually_drop", since = "1.20.0")]
270#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
271const impl<T: ?Sized> Deref for ManuallyDrop<T> {
272    type Target = T;
273    #[inline(always)]
274    fn deref(&self) -> &T {
275        self.value.as_ref()
276    }
277}
278
279#[stable(feature = "manually_drop", since = "1.20.0")]
280#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
281const impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
282    #[inline(always)]
283    fn deref_mut(&mut self) -> &mut T {
284        self.value.as_mut()
285    }
286}
287
288#[unstable(feature = "deref_pure_trait", issue = "87121")]
289unsafe impl<T: ?Sized> DerefPure for ManuallyDrop<T> {}
290
291#[stable(feature = "manually_drop", since = "1.20.0")]
292impl<T: ?Sized + Eq> Eq for ManuallyDrop<T> {}
293
294#[stable(feature = "manually_drop", since = "1.20.0")]
295impl<T: ?Sized + PartialEq> PartialEq for ManuallyDrop<T> {
296    fn eq(&self, other: &Self) -> bool {
297        self.value.as_ref().eq(other.value.as_ref())
298    }
299}
300
301#[stable(feature = "manually_drop", since = "1.20.0")]
302impl<T: ?Sized> StructuralPartialEq for ManuallyDrop<T> {}
303
304#[stable(feature = "manually_drop", since = "1.20.0")]
305impl<T: ?Sized + Ord> Ord for ManuallyDrop<T> {
306    fn cmp(&self, other: &Self) -> Ordering {
307        self.value.as_ref().cmp(other.value.as_ref())
308    }
309}
310
311#[stable(feature = "manually_drop", since = "1.20.0")]
312impl<T: ?Sized + PartialOrd> PartialOrd for ManuallyDrop<T> {
313    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
314        self.value.as_ref().partial_cmp(other.value.as_ref())
315    }
316}
317
318#[stable(feature = "manually_drop", since = "1.20.0")]
319impl<T: ?Sized + Hash> Hash for ManuallyDrop<T> {
320    fn hash<H: Hasher>(&self, state: &mut H) {
321        self.value.as_ref().hash(state);
322    }
323}