# The `Drop` trait

When we introduced [destructors](../03_ticket_v1/11_destructor.md),
we mentioned that the `drop` function:

1. reclaims the memory occupied by the type (i.e. `std::mem::size_of` bytes)
2. cleans up any additional resources that the value might be managing (e.g. the heap buffer of a `String`)

Step 2. is where the `Drop` trait comes in.

```rust
pub trait Drop {
    fn drop(&mut self);
}
```

The `Drop` trait is a mechanism for you to define _additional_ cleanup logic for your types,
beyond what the compiler does for you automatically.\
Whatever you put in the `drop` method will be executed when the value goes out of scope.

## `Drop` and `Copy`

When talking about the `Copy` trait, we said that a type can't implement `Copy` if it
manages additional resources beyond the `std::mem::size_of` bytes that it occupies in memory.

You might wonder: how does the compiler know if a type manages additional resources?
That's right: `Drop` trait implementations!\
If your type has an explicit `Drop` implementation, the compiler will assume
that your type has additional resources attached to it and won't allow you to implement `Copy`.

```rust
// This is a unit struct, i.e. a struct with no fields.
#[derive(Clone, Copy)]
struct MyType;

impl Drop for MyType {
    fn drop(&mut self) {
       // We don't need to do anything here,
       // it's enough to have an "empty" Drop implementation
    }
}
```

The compiler will complain with this error message:

```text
error[E0184]: the trait `Copy` cannot be implemented for this type; 
              the type has a destructor
 --> src/lib.rs:2:17
  |
2 | #[derive(Clone, Copy)]
  |                 ^^^^ `Copy` not allowed on types with destructors
```
