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