]>
Commit | Line | Data |
---|---|---|
dc9dc135 | 1 | use crate::ops::{Deref, DerefMut}; |
60c5eb7d | 2 | use crate::ptr; |
dc9dc135 XL |
3 | |
4 | /// A wrapper to inhibit compiler from automatically calling `T`’s destructor. | |
dc9dc135 XL |
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 | |
f9f354fc XL |
9 | /// about its contents. For example, initializing a `ManuallyDrop<&mut T>` |
10 | /// with [`mem::zeroed`] is undefined behavior. | |
dc9dc135 XL |
11 | /// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead. |
12 | /// | |
f9f354fc XL |
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 | /// | |
1b1a35ee | 18 | /// # `ManuallyDrop` and drop order. |
dc9dc135 | 19 | /// |
1b1a35ee XL |
20 | /// Rust has a well-defined [drop order] of values. To make sure that fields or |
21 | /// locals are dropped in a specific order, reorder the declarations such that | |
22 | /// the implicit drop order is the correct one. | |
dc9dc135 | 23 | /// |
1b1a35ee XL |
24 | /// It is possible to use `ManuallyDrop` to control the drop order, but this |
25 | /// requires unsafe code and is hard to do correctly in the presence of | |
26 | /// unwinding. | |
dc9dc135 | 27 | /// |
1b1a35ee XL |
28 | /// For example, if you want to make sure that a specific field is dropped after |
29 | /// the others, make it the last field of a struct: | |
dc9dc135 | 30 | /// |
1b1a35ee XL |
31 | /// ``` |
32 | /// struct Context; | |
f9f354fc | 33 | /// |
1b1a35ee XL |
34 | /// struct Widget { |
35 | /// children: Vec<Widget>, | |
36 | /// // `context` will be dropped after `children`. | |
37 | /// // Rust guarantees that fields are dropped in the order of declaration. | |
38 | /// context: Context, | |
39 | /// } | |
40 | /// ``` | |
f9f354fc | 41 | /// |
1b1a35ee | 42 | /// [drop order]: https://doc.rust-lang.org/reference/destructors.html |
3dfed10e XL |
43 | /// [`mem::zeroed`]: crate::mem::zeroed |
44 | /// [`MaybeUninit<T>`]: crate::mem::MaybeUninit | |
dc9dc135 XL |
45 | #[stable(feature = "manually_drop", since = "1.20.0")] |
46 | #[lang = "manually_drop"] | |
47 | #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] | |
48 | #[repr(transparent)] | |
49 | pub struct ManuallyDrop<T: ?Sized> { | |
50 | value: T, | |
51 | } | |
52 | ||
53 | impl<T> ManuallyDrop<T> { | |
54 | /// Wrap a value to be manually dropped. | |
55 | /// | |
56 | /// # Examples | |
57 | /// | |
58 | /// ```rust | |
59 | /// use std::mem::ManuallyDrop; | |
1b1a35ee XL |
60 | /// let mut x = ManuallyDrop::new(String::from("Hello World!")); |
61 | /// x.truncate(5); // You can still safely operate on the value | |
62 | /// assert_eq!(*x, "Hello"); | |
63 | /// // But `Drop` will not be run here | |
dc9dc135 | 64 | /// ``` |
1b1a35ee | 65 | #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"] |
dc9dc135 | 66 | #[stable(feature = "manually_drop", since = "1.20.0")] |
dfeec247 | 67 | #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] |
dc9dc135 XL |
68 | #[inline(always)] |
69 | pub const fn new(value: T) -> ManuallyDrop<T> { | |
70 | ManuallyDrop { value } | |
71 | } | |
72 | ||
73 | /// Extracts the value from the `ManuallyDrop` container. | |
74 | /// | |
75 | /// This allows the value to be dropped again. | |
76 | /// | |
77 | /// # Examples | |
78 | /// | |
79 | /// ```rust | |
80 | /// use std::mem::ManuallyDrop; | |
81 | /// let x = ManuallyDrop::new(Box::new(())); | |
82 | /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. | |
83 | /// ``` | |
84 | #[stable(feature = "manually_drop", since = "1.20.0")] | |
dfeec247 | 85 | #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] |
dc9dc135 XL |
86 | #[inline(always)] |
87 | pub const fn into_inner(slot: ManuallyDrop<T>) -> T { | |
88 | slot.value | |
89 | } | |
90 | ||
dfeec247 | 91 | /// Takes the value from the `ManuallyDrop<T>` container out. |
dc9dc135 XL |
92 | /// |
93 | /// This method is primarily intended for moving out values in drop. | |
94 | /// Instead of using [`ManuallyDrop::drop`] to manually drop the value, | |
95 | /// you can use this method to take the value and use it however desired. | |
dc9dc135 | 96 | /// |
74b04a01 | 97 | /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`] |
dfeec247 | 98 | /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`. |
dc9dc135 XL |
99 | /// |
100 | /// # Safety | |
101 | /// | |
dfeec247 XL |
102 | /// This function semantically moves out the contained value without preventing further usage, |
103 | /// leaving the state of this container unchanged. | |
104 | /// It is your responsibility to ensure that this `ManuallyDrop` is not used again. | |
dc9dc135 | 105 | /// |
dc9dc135 | 106 | #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] |
dfeec247 | 107 | #[stable(feature = "manually_drop_take", since = "1.42.0")] |
dc9dc135 XL |
108 | #[inline] |
109 | pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T { | |
f035d41b XL |
110 | // SAFETY: we are reading from a reference, which is guaranteed |
111 | // to be valid for reads. | |
112 | unsafe { ptr::read(&slot.value) } | |
dc9dc135 XL |
113 | } |
114 | } | |
115 | ||
116 | impl<T: ?Sized> ManuallyDrop<T> { | |
f9f354fc XL |
117 | /// Manually drops the contained value. This is exactly equivalent to calling |
118 | /// [`ptr::drop_in_place`] with a pointer to the contained value. As such, unless | |
119 | /// the contained value is a packed struct, the destructor will be called in-place | |
120 | /// without moving the value, and thus can be used to safely drop [pinned] data. | |
dc9dc135 XL |
121 | /// |
122 | /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead. | |
123 | /// | |
124 | /// # Safety | |
125 | /// | |
f9f354fc XL |
126 | /// This function runs the destructor of the contained value. Other than changes made by |
127 | /// the destructor itself, the memory is left unchanged, and so as far as the compiler is | |
128 | /// concerned still holds a bit-pattern which is valid for the type `T`. | |
129 | /// | |
130 | /// However, this "zombie" value should not be exposed to safe code, and this function | |
131 | /// should not be called more than once. To use a value after it's been dropped, or drop | |
132 | /// a value multiple times, can cause Undefined Behavior (depending on what `drop` does). | |
133 | /// This is normally prevented by the type system, but users of `ManuallyDrop` must | |
134 | /// uphold those guarantees without assistance from the compiler. | |
dc9dc135 | 135 | /// |
3dfed10e | 136 | /// [pinned]: crate::pin |
dc9dc135 XL |
137 | #[stable(feature = "manually_drop", since = "1.20.0")] |
138 | #[inline] | |
139 | pub unsafe fn drop(slot: &mut ManuallyDrop<T>) { | |
f035d41b XL |
140 | // SAFETY: we are dropping the value pointed to by a mutable reference |
141 | // which is guaranteed to be valid for writes. | |
142 | // It is up to the caller to make sure that `slot` isn't dropped again. | |
143 | unsafe { ptr::drop_in_place(&mut slot.value) } | |
dc9dc135 XL |
144 | } |
145 | } | |
146 | ||
147 | #[stable(feature = "manually_drop", since = "1.20.0")] | |
148 | impl<T: ?Sized> Deref for ManuallyDrop<T> { | |
149 | type Target = T; | |
150 | #[inline(always)] | |
151 | fn deref(&self) -> &T { | |
152 | &self.value | |
153 | } | |
154 | } | |
155 | ||
156 | #[stable(feature = "manually_drop", since = "1.20.0")] | |
157 | impl<T: ?Sized> DerefMut for ManuallyDrop<T> { | |
158 | #[inline(always)] | |
159 | fn deref_mut(&mut self) -> &mut T { | |
160 | &mut self.value | |
161 | } | |
162 | } |