]> git.lizzy.rs Git - rust.git/blob - library/core/src/mem/manually_drop.rs
Rollup merge of #75837 - GuillaumeGomez:fix-font-color-help-button, r=Cldfire
[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 subject to the same layout optimizations as `T`.
8 /// As a consequence, it has *no effect* on the assumptions that the compiler makes
9 /// about its contents. For example, initializing a `ManuallyDrop<&mut T>`
10 /// with [`mem::zeroed`] is undefined behavior.
11 /// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
12 ///
13 /// Note that accessing the value inside a `ManuallyDrop<T>` is safe.
14 /// This means that a `ManuallyDrop<T>` whose content has been dropped must not
15 /// be exposed through a public safe API.
16 /// Correspondingly, `ManuallyDrop::drop` is unsafe.
17 ///
18 /// # Examples
19 ///
20 /// This wrapper can be used to enforce a particular drop order on fields, regardless
21 /// of how they are defined in the struct:
22 ///
23 /// ```rust
24 /// use std::mem::ManuallyDrop;
25 /// struct Peach;
26 /// struct Banana;
27 /// struct Melon;
28 /// struct FruitBox {
29 ///     // Immediately clear there’s something non-trivial going on with these fields.
30 ///     peach: ManuallyDrop<Peach>,
31 ///     melon: Melon, // Field that’s independent of the other two.
32 ///     banana: ManuallyDrop<Banana>,
33 /// }
34 ///
35 /// impl Drop for FruitBox {
36 ///     fn drop(&mut self) {
37 ///         unsafe {
38 ///             // Explicit ordering in which field destructors are run specified in the intuitive
39 ///             // location – the destructor of the structure containing the fields.
40 ///             // Moreover, one can now reorder fields within the struct however much they want.
41 ///             ManuallyDrop::drop(&mut self.peach);
42 ///             ManuallyDrop::drop(&mut self.banana);
43 ///         }
44 ///         // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
45 ///         // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
46 ///     }
47 /// }
48 /// ```
49 ///
50 /// However, care should be taken when using this pattern as it can lead to *leak amplification*.
51 /// In this example, if the `Drop` implementation for `Peach` were to panic, the `banana` field
52 /// would also be leaked.
53 ///
54 /// In contrast, the automatically-generated compiler drop implementation would have ensured
55 /// that all fields are dropped even in the presence of panics. This is especially important when
56 /// working with [pinned] data, where reusing the memory without calling the destructor could lead
57 /// to Undefined Behaviour.
58 ///
59 /// [`mem::zeroed`]: crate::mem::zeroed
60 /// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
61 /// [pinned]: crate::pin
62 #[stable(feature = "manually_drop", since = "1.20.0")]
63 #[lang = "manually_drop"]
64 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
65 #[repr(transparent)]
66 pub struct ManuallyDrop<T: ?Sized> {
67     value: T,
68 }
69
70 impl<T> ManuallyDrop<T> {
71     /// Wrap a value to be manually dropped.
72     ///
73     /// # Examples
74     ///
75     /// ```rust
76     /// use std::mem::ManuallyDrop;
77     /// let mut x = ManuallyDrop::new(String::from("Hello World!"));
78     /// x.truncate(5); // You can still safely operate on the value
79     /// assert_eq!(*x, "Hello");
80     /// // But `Drop` will not be run here
81     /// ```
82     #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"]
83     #[stable(feature = "manually_drop", since = "1.20.0")]
84     #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")]
85     #[inline(always)]
86     pub const fn new(value: T) -> ManuallyDrop<T> {
87         ManuallyDrop { value }
88     }
89
90     /// Extracts the value from the `ManuallyDrop` container.
91     ///
92     /// This allows the value to be dropped again.
93     ///
94     /// # Examples
95     ///
96     /// ```rust
97     /// use std::mem::ManuallyDrop;
98     /// let x = ManuallyDrop::new(Box::new(()));
99     /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
100     /// ```
101     #[stable(feature = "manually_drop", since = "1.20.0")]
102     #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")]
103     #[inline(always)]
104     pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
105         slot.value
106     }
107
108     /// Takes the value from the `ManuallyDrop<T>` container out.
109     ///
110     /// This method is primarily intended for moving out values in drop.
111     /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
112     /// you can use this method to take the value and use it however desired.
113     ///
114     /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`]
115     /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`.
116     ///
117     /// # Safety
118     ///
119     /// This function semantically moves out the contained value without preventing further usage,
120     /// leaving the state of this container unchanged.
121     /// It is your responsibility to ensure that this `ManuallyDrop` is not used again.
122     ///
123     #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
124     #[stable(feature = "manually_drop_take", since = "1.42.0")]
125     #[inline]
126     pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
127         // SAFETY: we are reading from a reference, which is guaranteed
128         // to be valid for reads.
129         unsafe { ptr::read(&slot.value) }
130     }
131 }
132
133 impl<T: ?Sized> ManuallyDrop<T> {
134     /// Manually drops the contained value. This is exactly equivalent to calling
135     /// [`ptr::drop_in_place`] with a pointer to the contained value. As such, unless
136     /// the contained value is a packed struct, the destructor will be called in-place
137     /// without moving the value, and thus can be used to safely drop [pinned] data.
138     ///
139     /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
140     ///
141     /// # Safety
142     ///
143     /// This function runs the destructor of the contained value. Other than changes made by
144     /// the destructor itself, the memory is left unchanged, and so as far as the compiler is
145     /// concerned still holds a bit-pattern which is valid for the type `T`.
146     ///
147     /// However, this "zombie" value should not be exposed to safe code, and this function
148     /// should not be called more than once. To use a value after it's been dropped, or drop
149     /// a value multiple times, can cause Undefined Behavior (depending on what `drop` does).
150     /// This is normally prevented by the type system, but users of `ManuallyDrop` must
151     /// uphold those guarantees without assistance from the compiler.
152     ///
153     /// [pinned]: crate::pin
154     #[stable(feature = "manually_drop", since = "1.20.0")]
155     #[inline]
156     pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
157         // SAFETY: we are dropping the value pointed to by a mutable reference
158         // which is guaranteed to be valid for writes.
159         // It is up to the caller to make sure that `slot` isn't dropped again.
160         unsafe { ptr::drop_in_place(&mut slot.value) }
161     }
162 }
163
164 #[stable(feature = "manually_drop", since = "1.20.0")]
165 impl<T: ?Sized> Deref for ManuallyDrop<T> {
166     type Target = T;
167     #[inline(always)]
168     fn deref(&self) -> &T {
169         &self.value
170     }
171 }
172
173 #[stable(feature = "manually_drop", since = "1.20.0")]
174 impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
175     #[inline(always)]
176     fn deref_mut(&mut self) -> &mut T {
177         &mut self.value
178     }
179 }