@@ -15,50 +15,33 @@ use crate::ptr;
15
15
/// be exposed through a public safe API.
16
16
/// Correspondingly, `ManuallyDrop::drop` is unsafe.
17
17
///
18
- /// # Examples
18
+ /// # `ManuallyDrop` and drop order.
19
19
///
20
- /// This wrapper can be used to enforce a particular drop order on fields, regardless
21
- /// of how they are defined in the struct:
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.
22
23
///
23
- /// ```rust
24
- /// use std::mem::ManuallyDrop;
25
- /// struct Peach;
26
- /// struct Banana;
27
- /// struct Melon;
28
- /// struct FruitBox {
29
- /// // Immediately clear there’s something non-trivial going on with these fields.
30
- /// peach: ManuallyDrop<Peach>,
31
- /// melon: Melon, // Field that’s independent of the other two.
32
- /// banana: ManuallyDrop<Banana>,
33
- /// }
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.
34
27
///
35
- /// impl Drop for FruitBox {
36
- /// fn drop(&mut self) {
37
- /// unsafe {
38
- /// // Explicit ordering in which field destructors are run specified in the intuitive
39
- /// // location – the destructor of the structure containing the fields.
40
- /// // Moreover, one can now reorder fields within the struct however much they want.
41
- /// ManuallyDrop::drop(&mut self.peach);
42
- /// ManuallyDrop::drop(&mut self.banana);
43
- /// }
44
- /// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
45
- /// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
46
- /// }
47
- /// }
48
- /// ```
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:
49
30
///
50
- /// However, care should be taken when using this pattern as it can lead to *leak amplification*.
51
- /// In this example, if the `Drop` implementation for `Peach` were to panic, the `banana` field
52
- /// would also be leaked.
31
+ /// ```
32
+ /// struct Context;
53
33
///
54
- /// In contrast, the automatically-generated compiler drop implementation would have ensured
55
- /// that all fields are dropped even in the presence of panics. This is especially important when
56
- /// working with [pinned] data, where reusing the memory without calling the destructor could lead
57
- /// to Undefined Behaviour.
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
+ /// ```
58
41
///
42
+ /// [drop order]: https://doc.rust-lang.org/reference/destructors.html
59
43
/// [`mem::zeroed`]: crate::mem::zeroed
60
44
/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
61
- /// [pinned]: crate::pin
62
45
#[ stable( feature = "manually_drop" , since = "1.20.0" ) ]
63
46
#[ lang = "manually_drop" ]
64
47
#[ derive( Copy , Clone , Debug , Default , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
0 commit comments