]> git.lizzy.rs Git - rust.git/blob - library/core/src/mem/manually_drop.rs
Auto merge of #105590 - solid-rs:patch/kmc-solid/thread-lifecycle-ordering, r=m-ou-se
[rust.git] / library / core / src / mem / manually_drop.rs
1 use crate::ops::{Deref, DerefMut};
2 use crate::ptr;
3
4 /// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
5 /// This wrapper is 0-cost.
6 ///
7 /// `ManuallyDrop<T>` is guaranteed to have the same layout as `T`, and is subject
8 /// to the same layout optimizations as `T`. As a consequence, it has *no effect*
9 /// on the assumptions that the compiler makes about its contents. For example,
10 /// initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined
11 /// behavior. If you need to handle uninitialized data, use [`MaybeUninit<T>`]
12 /// instead.
13 ///
14 /// Note that accessing the value inside a `ManuallyDrop<T>` is safe.
15 /// This means that a `ManuallyDrop<T>` whose content has been dropped must not
16 /// be exposed through a public safe API.
17 /// 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 /// [drop order]: https://doc.rust-lang.org/reference/destructors.html
44 /// [`mem::zeroed`]: crate::mem::zeroed
45 /// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
46 #[stable(feature = "manually_drop", since = "1.20.0")]
47 #[lang = "manually_drop"]
48 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
49 #[repr(transparent)]
50 pub struct ManuallyDrop<T: ?Sized> {
51     value: T,
52 }
53
54 impl<T> ManuallyDrop<T> {
55     /// Wrap a value to be manually dropped.
56     ///
57     /// # Examples
58     ///
59     /// ```rust
60     /// use std::mem::ManuallyDrop;
61     /// let mut x = ManuallyDrop::new(String::from("Hello World!"));
62     /// x.truncate(5); // You can still safely operate on the value
63     /// assert_eq!(*x, "Hello");
64     /// // But `Drop` will not be run here
65     /// ```
66     #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"]
67     #[stable(feature = "manually_drop", since = "1.20.0")]
68     #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")]
69     #[inline(always)]
70     pub const fn new(value: T) -> ManuallyDrop<T> {
71         ManuallyDrop { value }
72     }
73
74     /// Extracts the value from the `ManuallyDrop` container.
75     ///
76     /// This allows the value to be dropped again.
77     ///
78     /// # Examples
79     ///
80     /// ```rust
81     /// use std::mem::ManuallyDrop;
82     /// let x = ManuallyDrop::new(Box::new(()));
83     /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
84     /// ```
85     #[stable(feature = "manually_drop", since = "1.20.0")]
86     #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")]
87     #[inline(always)]
88     pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
89         slot.value
90     }
91
92     /// Takes the value from the `ManuallyDrop<T>` container out.
93     ///
94     /// This method is primarily intended for moving out values in drop.
95     /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
96     /// you can use this method to take the value and use it however desired.
97     ///
98     /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`]
99     /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`.
100     ///
101     /// # Safety
102     ///
103     /// This function semantically moves out the contained value without preventing further usage,
104     /// leaving the state of this container unchanged.
105     /// It is your responsibility to ensure that this `ManuallyDrop` is not used again.
106     ///
107     #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
108     #[stable(feature = "manually_drop_take", since = "1.42.0")]
109     #[inline]
110     pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
111         // SAFETY: we are reading from a reference, which is guaranteed
112         // to be valid for reads.
113         unsafe { ptr::read(&slot.value) }
114     }
115 }
116
117 impl<T: ?Sized> ManuallyDrop<T> {
118     /// Manually drops the contained value. This is exactly equivalent to calling
119     /// [`ptr::drop_in_place`] with a pointer to the contained value. As such, unless
120     /// the contained value is a packed struct, the destructor will be called in-place
121     /// without moving the value, and thus can be used to safely drop [pinned] data.
122     ///
123     /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
124     ///
125     /// # Safety
126     ///
127     /// This function runs the destructor of the contained value. Other than changes made by
128     /// the destructor itself, the memory is left unchanged, and so as far as the compiler is
129     /// concerned still holds a bit-pattern which is valid for the type `T`.
130     ///
131     /// However, this "zombie" value should not be exposed to safe code, and this function
132     /// should not be called more than once. To use a value after it's been dropped, or drop
133     /// a value multiple times, can cause Undefined Behavior (depending on what `drop` does).
134     /// This is normally prevented by the type system, but users of `ManuallyDrop` must
135     /// uphold those guarantees without assistance from the compiler.
136     ///
137     /// [pinned]: crate::pin
138     #[stable(feature = "manually_drop", since = "1.20.0")]
139     #[inline]
140     pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
141         // SAFETY: we are dropping the value pointed to by a mutable reference
142         // which is guaranteed to be valid for writes.
143         // It is up to the caller to make sure that `slot` isn't dropped again.
144         unsafe { ptr::drop_in_place(&mut slot.value) }
145     }
146 }
147
148 #[stable(feature = "manually_drop", since = "1.20.0")]
149 #[rustc_const_unstable(feature = "const_deref", issue = "88955")]
150 impl<T: ?Sized> const Deref for ManuallyDrop<T> {
151     type Target = T;
152     #[inline(always)]
153     fn deref(&self) -> &T {
154         &self.value
155     }
156 }
157
158 #[stable(feature = "manually_drop", since = "1.20.0")]
159 #[rustc_const_unstable(feature = "const_deref", issue = "88955")]
160 impl<T: ?Sized> const DerefMut for ManuallyDrop<T> {
161     #[inline(always)]
162     fn deref_mut(&mut self) -> &mut T {
163         &mut self.value
164     }
165 }