@@ -7,14 +7,14 @@ use crate::ptr;
7
7
///
8
8
/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
9
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.
10
+ /// about its contents. For example , initializing a `ManuallyDrop<&mut T>`
11
+ /// with [`mem::zeroed`] is undefined behavior.
12
12
/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
13
13
///
14
14
/// # Examples
15
15
///
16
- /// This wrapper helps with explicitly documenting the drop order dependencies between fields of
17
- /// the type :
16
+ /// This wrapper can be used to enforce a particular drop order on fields, regardless
17
+ /// of how they are defined in the struct :
18
18
///
19
19
/// ```rust
20
20
/// use std::mem::ManuallyDrop;
@@ -43,8 +43,18 @@ use crate::ptr;
43
43
/// }
44
44
/// ```
45
45
///
46
+ /// However, care should be taken when using this pattern as it can lead to *leak amplification*.
47
+ /// In this example, if the `Drop` implementation for `Peach` were to panic, the `banana` field
48
+ /// would also be leaked.
49
+ ///
50
+ /// In contrast, the automatically-generated compiler drop implementation would have ensured
51
+ /// that all fields are dropped even in the presence of panics. This is especially important when
52
+ /// working with [pinned] data, where reusing the memory without calling the destructor could lead
53
+ /// to Undefined Behaviour.
54
+ ///
46
55
/// [`mem::zeroed`]: fn.zeroed.html
47
56
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
57
+ /// [pinned]: ../pin/index.html
48
58
#[ stable( feature = "manually_drop" , since = "1.20.0" ) ]
49
59
#[ lang = "manually_drop" ]
50
60
#[ derive( Copy , Clone , Debug , Default , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
@@ -113,19 +123,28 @@ impl<T> ManuallyDrop<T> {
113
123
}
114
124
115
125
impl < T : ?Sized > ManuallyDrop < T > {
116
- /// Manually drops the contained value.
126
+ /// Manually drops the contained value. This is exactly equivalent to calling
127
+ /// [`ptr::drop_in_place`] with a pointer to the contained value. As such, unless
128
+ /// the contained value is a packed struct, the destructor will be called in-place
129
+ /// without moving the value, and thus can be used to safely drop [pinned] data.
117
130
///
118
131
/// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
119
132
///
120
133
/// # Safety
121
134
///
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>`.
135
+ /// This function runs the destructor of the contained value. Other than changes made by
136
+ /// the destructor itself, the memory is left unchanged, and so as far as the compiler is
137
+ /// concerned still holds a bit-pattern which is valid for the type `T`.
138
+ ///
139
+ /// However, this "zombie" value should not be exposed to safe code, and this function
140
+ /// should not be called more than once. To use a value after it's been dropped, or drop
141
+ /// a value multiple times, can cause Undefined Behavior (depending on what `drop` does).
142
+ /// This is normally prevented by the type system, but users of `ManuallyDrop` must
143
+ /// uphold those guarantees without assistance from the compiler.
127
144
///
128
145
/// [`ManuallyDrop::into_inner`]: #method.into_inner
146
+ /// [`ptr::drop_in_place`]: ../ptr/fn.drop_in_place.html
147
+ /// [pinned]: ../pin/index.html
129
148
#[ stable( feature = "manually_drop" , since = "1.20.0" ) ]
130
149
#[ inline]
131
150
pub unsafe fn drop ( slot : & mut ManuallyDrop < T > ) {
0 commit comments