]> git.lizzy.rs Git - rust.git/blob - src/libcore/mem/manually_drop.rs
Rollup merge of #63055 - Mark-Simulacrum:save-analysis-clean-2, r=Xanewok
[rust.git] / src / libcore / mem / manually_drop.rs
1 use crate::ptr;
2 use crate::ops::{Deref, DerefMut};
3
4 /// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
5 ///
6 /// This wrapper is 0-cost.
7 ///
8 /// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
9 /// As a consequence, it has *no effect* on the assumptions that the compiler makes
10 /// about all values being initialized at their type.  In particular, initializing
11 /// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
12 /// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
13 ///
14 /// # Examples
15 ///
16 /// This wrapper helps with explicitly documenting the drop order dependencies between fields of
17 /// the type:
18 ///
19 /// ```rust
20 /// use std::mem::ManuallyDrop;
21 /// struct Peach;
22 /// struct Banana;
23 /// struct Melon;
24 /// struct FruitBox {
25 ///     // Immediately clear there’s something non-trivial going on with these fields.
26 ///     peach: ManuallyDrop<Peach>,
27 ///     melon: Melon, // Field that’s independent of the other two.
28 ///     banana: ManuallyDrop<Banana>,
29 /// }
30 ///
31 /// impl Drop for FruitBox {
32 ///     fn drop(&mut self) {
33 ///         unsafe {
34 ///             // Explicit ordering in which field destructors are run specified in the intuitive
35 ///             // location – the destructor of the structure containing the fields.
36 ///             // Moreover, one can now reorder fields within the struct however much they want.
37 ///             ManuallyDrop::drop(&mut self.peach);
38 ///             ManuallyDrop::drop(&mut self.banana);
39 ///         }
40 ///         // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
41 ///         // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
42 ///     }
43 /// }
44 /// ```
45 ///
46 /// [`mem::zeroed`]: fn.zeroed.html
47 /// [`MaybeUninit<T>`]: union.MaybeUninit.html
48 #[stable(feature = "manually_drop", since = "1.20.0")]
49 #[lang = "manually_drop"]
50 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
51 #[repr(transparent)]
52 pub struct ManuallyDrop<T: ?Sized> {
53     value: T,
54 }
55
56 impl<T> ManuallyDrop<T> {
57     /// Wrap a value to be manually dropped.
58     ///
59     /// # Examples
60     ///
61     /// ```rust
62     /// use std::mem::ManuallyDrop;
63     /// ManuallyDrop::new(Box::new(()));
64     /// ```
65     #[stable(feature = "manually_drop", since = "1.20.0")]
66     #[inline(always)]
67     pub const fn new(value: T) -> ManuallyDrop<T> {
68         ManuallyDrop { value }
69     }
70
71     /// Extracts the value from the `ManuallyDrop` container.
72     ///
73     /// This allows the value to be dropped again.
74     ///
75     /// # Examples
76     ///
77     /// ```rust
78     /// use std::mem::ManuallyDrop;
79     /// let x = ManuallyDrop::new(Box::new(()));
80     /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
81     /// ```
82     #[stable(feature = "manually_drop", since = "1.20.0")]
83     #[inline(always)]
84     pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
85         slot.value
86     }
87
88     /// Takes the contained value out.
89     ///
90     /// This method is primarily intended for moving out values in drop.
91     /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
92     /// you can use this method to take the value and use it however desired.
93     /// `Drop` will be invoked on the returned value following normal end-of-scope rules.
94     ///
95     /// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead.
96     ///
97     /// # Safety
98     ///
99     /// This function semantically moves out the contained value without preventing further usage.
100     /// It is up to the user of this method to ensure that this container is not used again.
101     ///
102     /// [`ManuallyDrop::drop`]: #method.drop
103     /// [`ManuallyDrop::into_inner`]: #method.into_inner
104     #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
105     #[unstable(feature = "manually_drop_take", issue = "55422")]
106     #[inline]
107     pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
108         ManuallyDrop::into_inner(ptr::read(slot))
109     }
110 }
111
112 impl<T: ?Sized> ManuallyDrop<T> {
113     /// Manually drops the contained value.
114     ///
115     /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
116     ///
117     /// # Safety
118     ///
119     /// This function runs the destructor of the contained value and thus the wrapped value
120     /// now represents uninitialized data. It is up to the user of this method to ensure the
121     /// uninitialized data is not actually used.
122     /// In particular, this function can only be called called at most once
123     /// for a given instance of `ManuallyDrop<T>`.
124     ///
125     /// [`ManuallyDrop::into_inner`]: #method.into_inner
126     #[stable(feature = "manually_drop", since = "1.20.0")]
127     #[inline]
128     pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
129         ptr::drop_in_place(&mut slot.value)
130     }
131 }
132
133 #[stable(feature = "manually_drop", since = "1.20.0")]
134 impl<T: ?Sized> Deref for ManuallyDrop<T> {
135     type Target = T;
136     #[inline(always)]
137     fn deref(&self) -> &T {
138         &self.value
139     }
140 }
141
142 #[stable(feature = "manually_drop", since = "1.20.0")]
143 impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
144     #[inline(always)]
145     fn deref_mut(&mut self) -> &mut T {
146         &mut self.value
147     }
148 }