about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/core/src/mem/manually_drop.rs55
1 files changed, 19 insertions, 36 deletions
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index aab0e96d83a..d86939454be 100644
--- a/library/core/src/mem/manually_drop.rs
+++ b/library/core/src/mem/manually_drop.rs
@@ -15,50 +15,33 @@ use crate::ptr;
 /// be exposed through a public safe API.
 /// Correspondingly, `ManuallyDrop::drop` is unsafe.
 ///
-/// # Examples
+/// # `ManuallyDrop` and drop order.
 ///
-/// This wrapper can be used to enforce a particular drop order on fields, regardless
-/// of how they are defined in the struct:
+/// Rust has a well-defined [drop order] of values. To make sure that fields or
+/// locals are dropped in a specific order, reorder the declarations such that
+/// the implicit drop order is the correct one.
 ///
-/// ```rust
-/// use std::mem::ManuallyDrop;
-/// struct Peach;
-/// struct Banana;
-/// struct Melon;
-/// struct FruitBox {
-///     // Immediately clear there’s something non-trivial going on with these fields.
-///     peach: ManuallyDrop<Peach>,
-///     melon: Melon, // Field that’s independent of the other two.
-///     banana: ManuallyDrop<Banana>,
-/// }
+/// It is possible to use `ManuallyDrop` to control the drop order, but this
+/// requires unsafe code and is hard to do correctly in the presence of
+/// unwinding.
 ///
-/// impl Drop for FruitBox {
-///     fn drop(&mut self) {
-///         unsafe {
-///             // Explicit ordering in which field destructors are run specified in the intuitive
-///             // location – the destructor of the structure containing the fields.
-///             // Moreover, one can now reorder fields within the struct however much they want.
-///             ManuallyDrop::drop(&mut self.peach);
-///             ManuallyDrop::drop(&mut self.banana);
-///         }
-///         // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
-///         // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
-///     }
-/// }
-/// ```
+/// For example, if you want to make sure that a specific field is dropped after
+/// the others, make it the last field of a struct:
 ///
-/// However, care should be taken when using this pattern as it can lead to *leak amplification*.
-/// In this example, if the `Drop` implementation for `Peach` were to panic, the `banana` field
-/// would also be leaked.
+/// ```
+/// struct Context;
 ///
-/// In contrast, the automatically-generated compiler drop implementation would have ensured
-/// that all fields are dropped even in the presence of panics. This is especially important when
-/// working with [pinned] data, where reusing the memory without calling the destructor could lead
-/// to Undefined Behaviour.
+/// struct Widget {
+///     children: Vec<Widget>,
+///     // `context` will be dropped after `children`.
+///     // Rust guarantees that fields are dropped in the order of declaration.
+///     context: Context,
+/// }
+/// ```
 ///
+/// [drop order]: https://doc.rust-lang.org/reference/destructors.html
 /// [`mem::zeroed`]: crate::mem::zeroed
 /// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
-/// [pinned]: crate::pin
 #[stable(feature = "manually_drop", since = "1.20.0")]
 #[lang = "manually_drop"]
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]