@@ -7,14 +7,14 @@ use crate::ptr;
77///
88/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
99/// 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.
1212/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
1313///
1414/// # Examples
1515///
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 :
1818///
1919/// ```rust
2020/// use std::mem::ManuallyDrop;
@@ -43,8 +43,18 @@ use crate::ptr;
4343/// }
4444/// ```
4545///
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+ ///
4655/// [`mem::zeroed`]: fn.zeroed.html
4756/// [`MaybeUninit<T>`]: union.MaybeUninit.html
57+ /// [pinned]: ../pin/index.html
4858#[ stable( feature = "manually_drop" , since = "1.20.0" ) ]
4959#[ lang = "manually_drop" ]
5060#[ derive( Copy , Clone , Debug , Default , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
@@ -113,19 +123,28 @@ impl<T> ManuallyDrop<T> {
113123}
114124
115125impl < 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.
117130 ///
118131 /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
119132 ///
120133 /// # Safety
121134 ///
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.
127144 ///
128145 /// [`ManuallyDrop::into_inner`]: #method.into_inner
146+ /// [`ptr::drop_in_place`]: ../ptr/fn.drop_in_place.html
147+ /// [pinned]: ../pin/index.html
129148 #[ stable( feature = "manually_drop" , since = "1.20.0" ) ]
130149 #[ inline]
131150 pub unsafe fn drop ( slot : & mut ManuallyDrop < T > ) {
0 commit comments