]> git.proxmox.com Git - rustc.git/blame - library/core/src/mem/manually_drop.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / library / core / src / mem / manually_drop.rs
CommitLineData
dc9dc135 1use crate::ops::{Deref, DerefMut};
60c5eb7d 2use 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)]
49pub struct ManuallyDrop<T: ?Sized> {
50 value: T,
51}
52
53impl<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
116impl<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")]
148impl<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")]
157impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
158 #[inline(always)]
159 fn deref_mut(&mut self) -> &mut T {
160 &mut self.value
161 }
162}