]> git.lizzy.rs Git - rust.git/blob - library/core/src/ops/drop.rs
Rollup merge of #103360 - ChrisDenton:isterm-filetype, r=thomcc
[rust.git] / library / core / src / ops / drop.rs
1 /// Custom code within the destructor.
2 ///
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.
8 ///
9 /// [the reference]: https://doc.rust-lang.org/reference/destructors.html
10 ///
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 all the fields of this value.
15 ///
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`.
23 ///
24 /// ## Examples
25 ///
26 /// To see destructors in action, let's take a look at the following program:
27 ///
28 /// ```rust
29 /// struct HasDrop;
30 ///
31 /// impl Drop for HasDrop {
32 ///     fn drop(&mut self) {
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!");
45 ///     }
46 /// }
47 ///
48 /// fn main() {
49 ///     let _x = HasTwoDrops { one: HasDrop, two: HasDrop };
50 ///     println!("Running!");
51 /// }
52 /// ```
53 ///
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
56 ///
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
66 ///
67 /// ```test
68 /// Running!
69 /// Dropping HasDrop!
70 /// Dropping HasDrop!
71 /// ```
72 ///
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 to explicitly call the destructor of a value, [`mem::drop`] can be used instead.
82 ///
83 /// [`mem::drop`]: drop
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 {
99 ///     fn drop(&mut self) {
100 ///         println!("Dropping Foo!")
101 ///     }
102 /// }
103 ///
104 /// struct Bar;
105 ///
106 /// impl Drop for Bar {
107 ///     fn drop(&mut self) {
108 ///         println!("Dropping Bar!")
109 ///     }
110 /// }
111 ///
112 /// fn main() {
113 ///     let _foo = Foo;
114 ///     let _bar = Bar;
115 /// }
116 /// ```
117 ///
118 /// This will print
119 ///
120 /// ```text
121 /// Dropping Bar!
122 /// Dropping Foo!
123 /// ```
124 ///
125 /// Please see [the reference] for the full rules.
126 ///
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 #[lang = "drop"]
136 #[stable(feature = "rust1", since = "1.0.0")]
137 #[const_trait]
138 pub trait Drop {
139     /// Executes the destructor for this type.
140     ///
141     /// This method is called implicitly when the value goes out of scope,
142     /// and cannot be called explicitly (this is compiler error [E0040]).
143     /// However, the [`mem::drop`] function in the prelude can be
144     /// used to call the argument's `Drop` implementation.
145     ///
146     /// When this method has been called, `self` has not yet been deallocated.
147     /// That only happens after the method is over.
148     /// If this wasn't the case, `self` would be a dangling reference.
149     ///
150     /// # Panics
151     ///
152     /// Given that a [`panic!`] will call `drop` as it unwinds, any [`panic!`]
153     /// in a `drop` implementation will likely abort.
154     ///
155     /// Note that even if this panics, the value is considered to be dropped;
156     /// you must not cause `drop` to be called again. This is normally automatically
157     /// handled by the compiler, but when using unsafe code, can sometimes occur
158     /// unintentionally, particularly when using [`ptr::drop_in_place`].
159     ///
160     /// [E0040]: ../../error_codes/E0040.html
161     /// [`panic!`]: crate::panic!
162     /// [`mem::drop`]: drop
163     /// [`ptr::drop_in_place`]: crate::ptr::drop_in_place
164     #[stable(feature = "rust1", since = "1.0.0")]
165     fn drop(&mut self);
166 }