|
1 | | -/// Used to run some code when a value goes out of scope. |
2 | | -/// This is sometimes called a 'destructor'. |
| 1 | +/// Custom code within the destructor. |
3 | 2 | /// |
4 | | -/// When a value goes out of scope, it will have its `drop` method called if |
5 | | -/// its type implements `Drop`. Then, any fields the value contains will also |
6 | | -/// be dropped recursively. |
| 3 | +/// When a value is no longer needed, Rust will run a "destructor" on that value. |
| 4 | +/// The most common way that a value is no longer needed is when it goes out of |
| 5 | +/// scope. Destructors may still run in other circumstances, but we're going to |
| 6 | +/// focus on scope for the examples here. To learn about some of those other cases, |
| 7 | +/// please see [the reference] section on destructors. |
7 | 8 | /// |
8 | | -/// Because of this recursive dropping, you do not need to implement this trait |
9 | | -/// unless your type needs its own destructor logic. |
| 9 | +/// [the reference]: https://doc.rust-lang.org/reference/destructors.html |
10 | 10 | /// |
11 | | -/// Refer to [the chapter on `Drop` in *The Rust Programming Language*][book] |
12 | | -/// for some more elaboration. |
| 11 | +/// This destructor consists of two components: |
| 12 | +/// - A call to `Drop::drop` for that value, if this special `Drop` trait is implemented for its type. |
| 13 | +/// - The automatically generated "drop glue" which recursively calls the destructors |
| 14 | +/// of the all fields of this value. |
13 | 15 | /// |
14 | | -/// [book]: ../../book/ch15-03-drop.html |
| 16 | +/// As Rust automatically calls the destructors of all contained fields, |
| 17 | +/// you don't have to implement `Drop` in most cases. But there are some cases where |
| 18 | +/// it is useful, for example for types which directly manage a resource. |
| 19 | +/// That resource may be memory, it may be a file descriptor, it may be a network socket. |
| 20 | +/// Once a value of that type is no longer going to be used, it should "clean up" its |
| 21 | +/// resource by freeing the memory or closing the file or socket. This is |
| 22 | +/// the job of a destructor, and therefore the job of `Drop::drop`. |
15 | 23 | /// |
16 | | -/// # Examples |
| 24 | +/// ## Examples |
17 | 25 | /// |
18 | | -/// ## Implementing `Drop` |
| 26 | +/// To see destructors in action, let's take a look at the following program: |
19 | 27 | /// |
20 | | -/// The `drop` method is called when `_x` goes out of scope, and therefore |
21 | | -/// `main` prints `Dropping!`. |
22 | | -/// |
23 | | -/// ``` |
| 28 | +/// ```rust |
24 | 29 | /// struct HasDrop; |
25 | 30 | /// |
26 | 31 | /// impl Drop for HasDrop { |
27 | 32 | /// fn drop(&mut self) { |
28 | | -/// println!("Dropping!"); |
| 33 | +/// println!("Dropping HasDrop!"); |
| 34 | +/// } |
| 35 | +/// } |
| 36 | +/// |
| 37 | +/// struct HasTwoDrops { |
| 38 | +/// one: HasDrop, |
| 39 | +/// two: HasDrop, |
| 40 | +/// } |
| 41 | +/// |
| 42 | +/// impl Drop for HasTwoDrops { |
| 43 | +/// fn drop(&mut self) { |
| 44 | +/// println!("Dropping HasTwoDrops!"); |
29 | 45 | /// } |
30 | 46 | /// } |
31 | 47 | /// |
32 | 48 | /// fn main() { |
33 | | -/// let _x = HasDrop; |
| 49 | +/// let _x = HasTwoDrops { one: HasDrop, two: HasDrop }; |
| 50 | +/// println!("Running!"); |
34 | 51 | /// } |
35 | 52 | /// ``` |
36 | 53 | /// |
37 | | -/// ## Dropping is done recursively |
| 54 | +/// Rust will first call `Drop::drop` for `_x` and then for both `_x.one` and `_x.two`, |
| 55 | +/// meaning that running this will print |
38 | 56 | /// |
39 | | -/// When `outer` goes out of scope, the `drop` method will be called first for |
40 | | -/// `Outer`, then for `Inner`. Therefore, `main` prints `Dropping Outer!` and |
41 | | -/// then `Dropping Inner!`. |
| 57 | +/// ```text |
| 58 | +/// Running! |
| 59 | +/// Dropping HasTwoDrops! |
| 60 | +/// Dropping HasDrop! |
| 61 | +/// Dropping HasDrop! |
| 62 | +/// ``` |
| 63 | +/// |
| 64 | +/// Even if we remove the implementation of `Drop` for `HasTwoDrop`, the destructors of its fields are still called. |
| 65 | +/// This would result in |
42 | 66 | /// |
| 67 | +/// ```test |
| 68 | +/// Running! |
| 69 | +/// Dropping HasDrop! |
| 70 | +/// Dropping HasDrop! |
43 | 71 | /// ``` |
44 | | -/// struct Inner; |
45 | | -/// struct Outer(Inner); |
46 | 72 | /// |
47 | | -/// impl Drop for Inner { |
| 73 | +/// ## You cannot call `Drop::drop` yourself |
| 74 | +/// |
| 75 | +/// Because `Drop::drop` is used to clean up a value, it may be dangerous to use this value after |
| 76 | +/// the method has been called. As `Drop::drop` does not take ownership of its input, |
| 77 | +/// Rust prevents misuse by not allowing you to call `Drop::drop` directly. |
| 78 | +/// |
| 79 | +/// In other words, if you tried to explicitly call `Drop::drop` in the above example, you'd get a compiler error. |
| 80 | +/// |
| 81 | +/// If you'd like explicitly call the destructor of a value, [`std::mem::drop`] can be used instead. |
| 82 | +/// |
| 83 | +/// [`std::mem::drop`]: ../../std/mem/fn.drop.html |
| 84 | +/// |
| 85 | +/// ## Drop order |
| 86 | +/// |
| 87 | +/// Which of our two `HasDrop` drops first, though? For structs, it's the same |
| 88 | +/// order that they're declared: first `one`, then `two`. If you'd like to try |
| 89 | +/// this yourself, you can modify `HasDrop` above to contain some data, like an |
| 90 | +/// integer, and then use it in the `println!` inside of `Drop`. This behavior is |
| 91 | +/// guaranteed by the language. |
| 92 | +/// |
| 93 | +/// Unlike for structs, local variables are dropped in reverse order: |
| 94 | +/// |
| 95 | +/// ```rust |
| 96 | +/// struct Foo; |
| 97 | +/// |
| 98 | +/// impl Drop for Foo { |
48 | 99 | /// fn drop(&mut self) { |
49 | | -/// println!("Dropping Inner!"); |
| 100 | +/// println!("Dropping Foo!") |
50 | 101 | /// } |
51 | 102 | /// } |
52 | 103 | /// |
53 | | -/// impl Drop for Outer { |
| 104 | +/// struct Bar; |
| 105 | +/// |
| 106 | +/// impl Drop for Bar { |
54 | 107 | /// fn drop(&mut self) { |
55 | | -/// println!("Dropping Outer!"); |
| 108 | +/// println!("Dropping Bar!") |
56 | 109 | /// } |
57 | 110 | /// } |
58 | 111 | /// |
59 | 112 | /// fn main() { |
60 | | -/// let _x = Outer(Inner); |
| 113 | +/// let _foo = Foo; |
| 114 | +/// let _bar = Bar; |
61 | 115 | /// } |
62 | 116 | /// ``` |
63 | 117 | /// |
64 | | -/// ## Variables are dropped in reverse order of declaration |
65 | | -/// |
66 | | -/// `_first` is declared first and `_second` is declared second, so `main` will |
67 | | -/// print `Declared second!` and then `Declared first!`. |
| 118 | +/// This will print |
68 | 119 | /// |
| 120 | +/// ```text |
| 121 | +/// Dropping Bar! |
| 122 | +/// Dropping Foo! |
69 | 123 | /// ``` |
70 | | -/// struct PrintOnDrop(&'static str); |
71 | 124 | /// |
72 | | -/// impl Drop for PrintOnDrop { |
73 | | -/// fn drop(&mut self) { |
74 | | -/// println!("{}", self.0); |
75 | | -/// } |
76 | | -/// } |
| 125 | +/// Please see [the reference] for the full rules. |
77 | 126 | /// |
78 | | -/// fn main() { |
79 | | -/// let _first = PrintOnDrop("Declared first!"); |
80 | | -/// let _second = PrintOnDrop("Declared second!"); |
81 | | -/// } |
82 | | -/// ``` |
| 127 | +/// [the reference]: https://doc.rust-lang.org/reference/destructors.html |
| 128 | +/// |
| 129 | +/// ## `Copy` and `Drop` are exclusive |
| 130 | +/// |
| 131 | +/// You cannot implement both [`Copy`] and `Drop` on the same type. Types that |
| 132 | +/// are `Copy` get implicitly duplicated by the compiler, making it very |
| 133 | +/// hard to predict when, and how often destructors will be executed. As such, |
| 134 | +/// these types cannot have destructors. |
| 135 | +/// |
| 136 | +/// [`Copy`]: ../../std/marker/trait.Copy.html |
83 | 137 | #[lang = "drop"] |
84 | 138 | #[stable(feature = "rust1", since = "1.0.0")] |
85 | 139 | pub trait Drop { |
|
0 commit comments