]> git.lizzy.rs Git - rust.git/blob - src/libcore/mem/manually_drop.rs
Rollup merge of #71140 - oli-obk:static_cycle, r=RalfJung
[rust.git] / src / libcore / 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 ///
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     #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")]
67     #[inline(always)]
68     pub const fn new(value: T) -> ManuallyDrop<T> {
69         ManuallyDrop { value }
70     }
71
72     /// Extracts the value from the `ManuallyDrop` container.
73     ///
74     /// This allows the value to be dropped again.
75     ///
76     /// # Examples
77     ///
78     /// ```rust
79     /// use std::mem::ManuallyDrop;
80     /// let x = ManuallyDrop::new(Box::new(()));
81     /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
82     /// ```
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 into_inner(slot: ManuallyDrop<T>) -> T {
87         slot.value
88     }
89
90     /// Takes the value from the `ManuallyDrop<T>` container out.
91     ///
92     /// This method is primarily intended for moving out values in drop.
93     /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
94     /// you can use this method to take the value and use it however desired.
95     ///
96     /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`]
97     /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`.
98     ///
99     /// # Safety
100     ///
101     /// This function semantically moves out the contained value without preventing further usage,
102     /// leaving the state of this container unchanged.
103     /// It is your responsibility to ensure that this `ManuallyDrop` is not used again.
104     ///
105     /// [`ManuallyDrop::drop`]: #method.drop
106     /// [`ManuallyDrop::into_inner`]: #method.into_inner
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         ptr::read(&slot.value)
112     }
113 }
114
115 impl<T: ?Sized> ManuallyDrop<T> {
116     /// Manually drops the contained value.
117     ///
118     /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
119     ///
120     /// # Safety
121     ///
122     /// This function runs the destructor of the contained value and thus the wrapped value
123     /// now represents uninitialized data. It is up to the user of this method to ensure the
124     /// uninitialized data is not actually used.
125     /// In particular, this function can only be called at most once
126     /// for a given instance of `ManuallyDrop<T>`.
127     ///
128     /// [`ManuallyDrop::into_inner`]: #method.into_inner
129     #[stable(feature = "manually_drop", since = "1.20.0")]
130     #[inline]
131     pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
132         ptr::drop_in_place(&mut slot.value)
133     }
134 }
135
136 #[stable(feature = "manually_drop", since = "1.20.0")]
137 impl<T: ?Sized> Deref for ManuallyDrop<T> {
138     type Target = T;
139     #[inline(always)]
140     fn deref(&self) -> &T {
141         &self.value
142     }
143 }
144
145 #[stable(feature = "manually_drop", since = "1.20.0")]
146 impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
147     #[inline(always)]
148     fn deref_mut(&mut self) -> &mut T {
149         &mut self.value
150     }
151 }