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