pub trait Drop {
// Required method
fn drop(&mut self);
}
Expand description
Custom code within the destructor.
When a value is no longer needed, Rust will run a “destructor” on that value. The most common way that a value is no longer needed is when it goes out of scope. Destructors may still run in other circumstances, but we’re going to focus on scope for the examples here. To learn about some of those other cases, please see the reference section on destructors.
This destructor consists of two components:
- A call to
Drop::drop
for that value, if this specialDrop
trait is implemented for its type. - The automatically generated “drop glue” which recursively calls the destructors of all the fields of this value.
As Rust automatically calls the destructors of all contained fields,
you don’t have to implement Drop
in most cases. But there are some cases where
it is useful, for example for types which directly manage a resource.
That resource may be memory, it may be a file descriptor, it may be a network socket.
Once a value of that type is no longer going to be used, it should “clean up” its
resource by freeing the memory or closing the file or socket. This is
the job of a destructor, and therefore the job of Drop::drop
.
§Examples
To see destructors in action, let’s take a look at the following program:
struct HasDrop;
impl Drop for HasDrop {
fn drop(&mut self) {
println!("Dropping HasDrop!");
}
}
struct HasTwoDrops {
one: HasDrop,
two: HasDrop,
}
impl Drop for HasTwoDrops {
fn drop(&mut self) {
println!("Dropping HasTwoDrops!");
}
}
fn main() {
let _x = HasTwoDrops { one: HasDrop, two: HasDrop };
println!("Running!");
}
Rust will first call Drop::drop
for _x
and then for both _x.one
and _x.two
,
meaning that running this will print
Running!
Dropping HasTwoDrops!
Dropping HasDrop!
Dropping HasDrop!
Even if we remove the implementation of Drop
for HasTwoDrop
, the destructors of its fields are still called.
This would result in
Running!
Dropping HasDrop!
Dropping HasDrop!
§You cannot call Drop::drop
yourself
Because Drop::drop
is used to clean up a value, it may be dangerous to use this value after
the method has been called. As Drop::drop
does not take ownership of its input,
Rust prevents misuse by not allowing you to call Drop::drop
directly.
In other words, if you tried to explicitly call Drop::drop
in the above example, you’d get a compiler error.
If you’d like to explicitly call the destructor of a value, mem::drop
can be used instead.