# Drop & defer

## Drop: your destructor

A struct that defines a method literally named `drop` runs that method on scope exit. The signature is fixed: `fn drop(mut self)`, with no return type.

```cplus
struct Buf { ptr: *u8, len: usize }
impl Buf {
    fn drop(mut self) {
        unsafe { free(self.ptr); }
    }
}

fn main() -> i32 {
    let b: Buf = make_buf();
    // ... use b ...
    return 0;
}                                    // b.drop() runs here
```

Defining `drop` makes the type non-`Copy`, which is necessary: copying a value that owns a resource would lead to a double free. See [Ownership](/docs/ownership) for how `Copy` is derived.

## Raw-pointer accountability

A `drop` frees its struct's fields by hand; the compiler does not synthesize per-field drops. For a raw-pointer field (`*T`) the compiler cannot tell whether the struct owns the memory or only borrows it, so it makes you say which. A raw-pointer field that is neither released by the struct's `drop` nor marked `opaque` is a compile error (**E0510**). There is no silent-leak default.

```cplus
struct Buf { ptr: *u8, len: usize }
impl Buf {
    fn drop(mut self) { unsafe { free(self.ptr); } }   // owned: you free what you own
}

struct View { opaque ptr: *u8, len: usize }            // borrowed: `opaque` means "not mine"
```

Severity tracks what the compiler can prove about the `drop` body. It is a structural check, with no dataflow:

| The field's release in `drop` is... | Result |
|---|---|
| unconditional, or guarded only by a null-test on the same field | clean |
| present but conditional (a refcount, flag, or loop, so it cannot be proven to always run) | **W0002** warning |
| absent, delegated to a helper, or there is no `drop` at all | **E0510** error |
| the field is marked `opaque` | clean (managed elsewhere) |

`free(self.ptr as *u8)` counts as releasing `ptr`, since the cast is transparent. The warning case is for legitimately conditional owners such as refcounted types, which free their control block only on the last reference. Use `opaque` only when another owner truly frees the pointer: an FFI handle the runtime owns, a borrowed view, or a pointer freed by a sibling struct.

## `defer`: run at scope exit, LIFO

`defer` schedules an action to run when the scope exits, in last-in-first-out order:

```cplus
fn main() -> i32 {
    println(1);
    defer println(4);
    defer println(3);
    println(2);
    return 0;
}
// Prints 1, 2, 3, 4
```

`defer` and `Drop` share one scope-exit stack: they interleave in declaration order and are popped LIFO at exit.
