|
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