<p>In Rust, the <code>Drop</code> trait is defined like this:</p>
<pre class="lang-rs prettyprint-override"><code>trait Drop {
    fn drop(&amp;mut self);
}
</code></pre>
<p>This has a number of issues:</p>
<ul>
<li>If you would call the method manually, it would cause the object to be in a partially destructed state, that might be unsafe. Rust special cases this method and doesn't allow it to be called. If drop took <code>self</code> as an argument instead there would still need to be a special case to prevent it from being called twice but that feels less arbitrary.</li>
<li>You can't control the order different fields are destructed, or prevent their destruction. This would be trivial if the method took <code>self</code> as an argument as you could <code>forget</code> or <code>drop</code> each field with whatever order or method desired, or they could still be automatically dropped if you didn't do anything with them.</li>
</ul>
<p>Are there any reasons I'm missing why drop taking <code>self</code> would hurt soundness? Is there any source for why the trait was designed this way?</p>

<rust><destructors>
In Rust, why did the designers choose to make drop take &mut self instead of self
CC BY-SA 4.0
2024-07-05T13:09:26.233Z
I can think of two simple reasons ─ one is that transferring ownership implies a move, which might not always be optimised out; the other is that ownership would allow a custom implementation to *not* drop the value, instead keeping it alive. That wouldn't be unsound (a custom implementation could instead keep a copy alive, with essentially the same results), but it would be perverse and potentially could be done by accident.
kaya3
CC BY-SA 4.0
2024-07-05T13:13:29.267Z
@kaya3 Not droping a value is, in Rust, not considered unsafe though.
mousetail 'he-him'
CC BY-SA 4.0
2024-07-05T13:24:45.800Z
Yes, so it's not unsafe/unsound, but it would be strange if a custom implementation of the `Drop` trait was allowed to not drop the value.
kaya3
CC BY-SA 4.0
2024-07-05T13:52:40.573Z
@kaya3 The entire point though is to allow not dropping a field, or dropping it in a custom way other than the default. Right now that requires using `ManuallyDrop<T>` and unsafe code. Sure the default should be to drop the fields but there are good reasons why you might not want to, and needing to reach for unsafe seems odd since doing this does not actually risk UB.
mousetail 'he-him'
CC BY-SA 4.0
2024-07-05T19:28:20.213Z
Not sure if this is the answer, but if `drop` took `self` by value, it would drop it at the end by default, triggering an infinite recursion.
Sebastian Reichelt
CC BY-SA 4.0
2024-07-05T19:33:55.890Z
@SebastianReichelt Yes, that would need to be special cased
mousetail 'he-him'
CC BY-SA 4.0
2024-10-10T13:08:28.603Z
I assume this is a common question because [the Rust book has an exercise](https://doc.rust-lang.org/book/ch20-03-graceful-shutdown-and-cleanup.html) where two fields are wrapped in `Option<T>` just to satisfy the borrow checker during drop. The [corresponding question on StackOverflow](https://stackoverflow.com/q/30905826/252218) also left me unsatisfied.
BoppreH
<p><strong>If <code>Drop::drop</code> took <code>self</code> by value, it would infinitely recurse.</strong></p>
<p>In the simplest case, <code>self</code> would be dropped again at the end of <code>Drop::drop</code>'s scope, calling <code>Drop::drop</code> again, causing <code>self</code> to be dropped again, and so on.</p>
<hr />
<p>But wait, couldn't <code>Drop::drop</code> be special-cased, so that it destroys <code>self</code> regularly? <strong>The problem is, it's not necessarily <code>Drop::drop</code> that would be destroying <code>self</code>.</strong> Consider:</p>
<pre class="lang-rust prettyprint-override"><code>struct Foo { 
    // ... some fields
}

fn do_something(foo: Foo) {
    // ... some code
    foo;
}

impl Drop for Foo {
    fn drop(self) {
        do_something(self);
    }
}
</code></pre>
<p>Here, the drop code for <code>Foo</code> isn't in <code>Drop::drop</code>, it's in <code>do_something</code>.</p>
<p>In this particular example, <code>Drop::drop</code> could call a special version of <code>do_something</code> that doesn't drop <code>Foo</code>. But <strong>the general problem is unsolvable.</strong> Consider:</p>
<pre class="lang-rust prettyprint-override"><code>struct Foo {
    fun: fn()
}

static FOO: Mutex&lt;Option&lt;Foo&gt;&gt; = Mutex::new(None);

fn do_something(foo: Foo) {
    let fun = foo.fun;
    FOO.lock().insert(foo);
    fun();
}

impl Drop for Foo {
    fn drop(self) {
        do_something(self);
    }
}

fn do_something_else() {
    FOO.lock().take();
}

fn main() {
    let foo = Foo { fun: do_something_else };
}
</code></pre>
<p>Here, the call to <code>main</code> drops <code>foo = Foo { fun: do_something_else }</code>, which calls <code>Drop::drop</code>, which calls <code>do_something</code>, which inserts <code>foo</code> into <code>FOO</code>, then calls <code>do_something_else</code>, which takes <code>foo</code> out of <code>FOO</code>, then drops <code>foo</code> again...infinite recursion. And the static analysis to detect and prevent this is hard to the point of being infeasible (there are possible examples that are more convoluted).</p>
<hr />
<p><strong>One possible workaround is to implicitly add a boolean in every <code>Drop</code>-implementing type</strong> that is set when the instance gets dropped the first time, and dropping when already set regularly destroys the instance. But this goes against Rust's goal to have maximum efficiency and minimum hidden complexity; no other <code>impl</code> block changes a type's structure. Furthermore, this would prevent <code>Drop</code> from being implemented on <code>repr(transparent)</code> types.</p>
<p><strong>Another workaround is to prevent <code>Drop::drop</code> from wholly moving <code>self</code>, only individual fields.</strong> In fact, I could see the developers going with instead of <code>&amp;mut self</code>. Nonetheless, it adds complexity to an already complex language, especially the <code>Drop</code> trait which <a href="https://doc.rust-lang.org/nomicon/dropck.html" rel="noreferrer">already has extra restrictions</a>.</p>
<hr />
<p>Meanwhile, <strong><code>Drop::drop</code> taking <code>&amp;mut self</code> isn't a big problem, because it can be worked around in multiple ways:</strong></p>
<ul>
<li><strong>In safe Rust: by replacing <code>self</code> with dummy data</strong>.</li>
</ul>
<pre class="lang-rust prettyprint-override"><code>#[derive(Default)]
struct Foo {
    // ... some fields implementing `Default`
}

impl Drop for Foo {
    fn drop(&amp;mut self) {
        let this = std::mem::take(self);
        // ... now you have a value `this`
    }
}
</code></pre>
<p>If you don't want to implement <code>Default</code>, you can use <code>std::mem::replace</code> and some random values. If a field's type doesn't permit &quot;dummy&quot; instances, you can sacrifice a bit of efficiency and cleanness by wrapping the field in <code>Option</code>, where it will always be <code>Some</code> except in <code>Drop::drop</code>.</p>
<ul>
<li><strong>In unsafe Rust: by wrapping the type with <a href="https://doc.rust-lang.org/std/mem/struct.ManuallyDrop.html" rel="noreferrer"><code>ManuallyDrop</code></a>.</strong></li>
</ul>
<pre class="lang-rust prettyprint-override"><code>struct Foo(ManuallyDrop&lt;FooRepr&gt;);

struct FooRepr {
    // ... some fields implementing `Default`
}

impl Foo {
    pub fn new(
        // ... FooRepr fields
    ) -&gt; Self {
        Self(ManuallyDrop::new(FooRepr {
            // ...
        }))
    }
}

impl Deref for Foo {
    type Target = FooRepr;

    fn deref(&amp;self) -&gt; &amp;Self::Target {
        self.0.deref()
    }
}

impl DerefMut for Foo {
    fn deref_mut(&amp;mut self) -&gt; &amp;mut Self::Target {
        self.0.deref_mut()
    }
}

impl Drop for Foo {
    fn drop(&amp;mut self) {
        let foo = unsafe { ManuallyDrop::take(&amp;mut self.0) };
    }
}
</code></pre>
<p>Also note that, if you only care about moving some of <code>self</code>'s fields, you can replace-with-stub or wrap the individual fields instead of the entire value.</p>

CC BY-SA 4.0
2024-07-06T08:18:03.663Z
2024-07-06T08:18:03.663Z
tarzh
CC BY-SA 4.0
2024-07-06T08:22:52.247Z
I think this is most likely true, but since the question is about *why the designers chose* this approach it would be ideal to point at some supporting information on that side (which presumably does exist, given the Rust development process).
Michael Homer
CC BY-SA 4.0
2024-07-06T13:05:41.130Z
Swift made `deinit` take `self` as an *im*mutable borrow, because mutating methods are allowed to consume `self` and then assign a new value to it (which would cause `deinit` to recurse). Is this not an issue in Rust?
Bbrk24
CC BY-SA 4.0
2024-07-08T03:41:10.280Z
@Bbrk24 it is possible in Rust with `std::mem::swap`. Likewise, it's possible to get an infinitely-recursing `Drop::drop(&mut self)`, the easiest way just doing `self.clone()` since then the clone will be dropped. But it's not an issue the same way `Drop::drop(self)` is. The thing with `Drop::drop(self)`, is that it would *have* to be special-cased because even an empty function would drop. And then it's not immediately clear what to do when `self` is passed to another function; if that is disallowed, it means the body of `Drop::drop` has special rules that no other function has.
tarzh
CC BY-SA 4.0
2024-07-08T05:01:14.560Z
Although `Drop::drop` already has special rules for how its called...
tarzh
CC BY-SA 4.0
2024-07-08T05:23:42.990Z
@MichaelHomer other than [a stack exchange post](https://stackoverflow.com/a/30905994) with roughly the same answer, and some Reddit and forum posts asking how to move dropped fields, the only thing I found were the the commits where `drop` was added. It was *really* early in development (before the `Drop` trait, there were `drop { ... }` blocks).
tarzh
CC BY-SA 4.0
2024-07-08T05:50:05.627Z
So I finally found this: **https://github.com/rust-lang/rust/issues/2955**. It looks like the idea to let destructors move out fields was proposed in 2012, but it was dropped due to "not adding expressiveness" due to the `Option` (in today's Rust I suspect it would be more like `ManuallyDrop`) workaround.
tarzh
CC BY-SA 4.0
2024-07-09T02:10:25.627Z
It’s not that the problem is unsolvable imo, it’s that we already have a decent solution. Infinite recursion like you describe can only be caused by resurrection, which can only be caused by escape. You could add language features to prevent escape of `self`, but it’s surprisingly involved, and `&mut self` already does the right thing. Wrapping the innards of `Drop` types in `ManuallyDrop` is the right solution, though it’d be nice if it were safe and a bit simpler.
Jon Purdy
CC BY-SA 4.0
2024-07-10T15:40:28.290Z
Doesn't your example using `std::mem::take` also recurse infinitely? `this` will have to be dropped at the end of the function.
kaya3
CC BY-SA 4.0
2024-07-10T21:00:27.083Z
No, because `this.0`/`FooRepr` is being dropped.
tarzh
<p>Let's go spelunking!</p>
<p><strong>TL;DR: Too many special rules would be necessary.</strong></p>
<p>A quick Google search leads to <a href="https://github.com/rust-lang/rust/issues/4330" rel="noreferrer">#4330</a>: <em>drop could take self by-value, and allow early destruction</em>, Jan 2nd, 2013.</p>
<p><code>drop</code> was already taking a reference at this point, and @thestinger asked whether it should be switched to by value. @nikomatsakis was in favor, but the change did not go through as per <a href="https://github.com/rust-lang/rust/issues/4330#issuecomment-26852226" rel="noreferrer">the comment by @alexcrichton</a>:</p>
<blockquote>
<p>We decided in today's meeting (<a href="https://github.com/mozilla/rust/wiki/Meeting-weekly-2013-10-22" rel="noreferrer">https://github.com/mozilla/rust/wiki/Meeting-weekly-2013-10-22</a>) that <strong>drop by value requires too many special rules and semantics about it to warrant the convenience of taking self by value instead of by reference</strong> <em>[emphasis mine]</em>. For that reason, I'm de-milestoning the bug, removing the P-backcompat-lang label, and removing the I-completion label.</p>
<p>While we don't plan on doing this for 1.0, there is always the possibility of doing it afterwards. It would be a little painful, but types could implement a <code>DropValue</code> trait if necessary and the compiler would require that both <code>Drop</code> and <code>DropValue</code> are not implemented for the same type. This means that I don't want to close this bug, because it would continue to be an interesting issue to investigate. In the meantime, however, this is not going to be a priority.</p>
</blockquote>
<p>Unfortunately, the link to the meeting notes is dead, and the Wayback machine only has 1 single save from Nov. 2020 where it was already a 301 redirect to a non-existing page.</p>
<hr />
<p>On a personal note, I don't see many alternatives to <code>&amp;mut self</code>:</p>
<ul>
<li>By value will indeed require some rules to avoid infinite recursions, especially when the value is further moved to regular functions. The fabled <code>&amp;own self</code> mode would run into the same issues.</li>
<li>Splitting the value into its fields would prevent calling methods on the value. For example, a <code>Drop</code> for <code>Vec</code> will first call <code>.clear()</code> to destroy all elements prior to releasing the memory, which requires the value as a whole.</li>
</ul>

CC BY-SA 4.0
2024-07-10T15:15:05.493Z
2024-07-10T15:15:05.493Z
Matthieu M.
# In Rust, why did the designers choose to make drop take &mut self instead of self
Posted by: username_0 on 2024-07-04
In Rust, the Drop trait is defined like this:
trait Drop {
    fn drop(&mut self);
}

This has a number of issues:

If you would call the method manually, it would cause the object to be in a partially destructed state, that might be unsafe. Rust special cases this method and doesn't allow it to be called. If drop took self as an argument instead there would still need to be a special case to prevent it from being called twice but that feels less arbitrary.
You can't control the order different fields are destructed, or prevent their destruction. This would be trivial if the method took self as an argument as you could forget or drop each field with whatever order or method desired, or they could still be automatically dropped if you didn't do anything with them.

Are there any reasons I'm missing why drop taking self would hurt soundness? Is there any source for why the trait was designed this way?
**Tags:** rust destructors
> **Comments:**
> **username_1**: I can think of two simple reasons ─ one is that transferring ownership implies a move, which might not always be optimised out; the other is that ownership would allow a custom implementation to *not* drop the value, instead keeping it alive. That wouldn't be unsound (a custom implementation could instead keep a copy alive, with essentially the same results), but it would be perverse and potentially could be done by accident.  
> **username_0**: @kaya3 Not droping a value is, in Rust, not considered unsafe though.  
> **username_1**: Yes, so it's not unsafe/unsound, but it would be strange if a custom implementation of the `Drop` trait was allowed to not drop the value.  
> **username_0**: @kaya3 The entire point though is to allow not dropping a field, or dropping it in a custom way other than the default. Right now that requires using `ManuallyDrop<T>` and unsafe code. Sure the default should be to drop the fields but there are good reasons why you might not want to, and needing to reach for unsafe seems odd since doing this does not actually risk UB.  
> **username_2**: Not sure if this is the answer, but if `drop` took `self` by value, it would drop it at the end by default, triggering an infinite recursion.  
> **username_0**: @SebastianReichelt Yes, that would need to be special cased  
> **username_3**: I assume this is a common question because [the Rust book has an exercise](https://doc.rust-lang.org/book/ch20-03-graceful-shutdown-and-cleanup.html) where two fields are wrapped in `Option<T>` just to satisfy the borrow checker during drop. The [corresponding question on StackOverflow](https://stackoverflow.com/q/30905826/252218) also left me unsatisfied.  
---
## 2 answers
### Answer by username_8 on 2024-07-10. Score: 6 | Accepted answer
Let's go spelunking!

**TL;DR: Too many special rules would be necessary.**

A quick Google search leads to [#4330](https://github.com/rust-lang/rust/issues/4330): *drop could take self by-value, and allow early destruction*, Jan 2nd, 2013.

`drop` was already taking a reference at this point, and @thestinger asked whether it should be switched to by value. @nikomatsakis was in favor, but the change did not go through as per [the comment by @alexcrichton](https://github.com/rust-lang/rust/issues/4330#issuecomment-26852226):

> We decided in today's meeting (<https://github.com/mozilla/rust/wiki/Meeting-weekly-2013-10-22>) that **drop by value requires too many special rules and semantics about it to warrant the convenience of taking self by value instead of by reference** *[emphasis mine]*. For that reason, I'm de-milestoning the bug, removing the P-backcompat-lang label, and removing the I-completion label.
>
> While we don't plan on doing this for 1.0, there is always the possibility of doing it afterwards. It would be a little painful, but types could implement a `DropValue` trait if necessary and the compiler would require that both `Drop` and `DropValue` are not implemented for the same type. This means that I don't want to close this bug, because it would continue to be an interesting issue to investigate. In the meantime, however, this is not going to be a priority.

Unfortunately, the link to the meeting notes is dead, and the Wayback machine only has 1 single save from Nov. 2020 where it was already a 301 redirect to a non-existing page.

---

On a personal note, I don't see many alternatives to `&mut self`:

* By value will indeed require some rules to avoid infinite recursions, especially when the value is further moved to regular functions. The fabled `&own self` mode would run into the same issues.
* Splitting the value into its fields would prevent calling methods on the value. For example, a `Drop` for `Vec` will first call `.clear()` to destroy all elements prior to releasing the memory, which requires the value as a whole.
---
### Answer by username_4 on 2024-07-06. Score: 5
If Drop::drop took self by value, it would infinitely recurse.
In the simplest case, self would be dropped again at the end of Drop::drop's scope, calling Drop::drop again, causing self to be dropped again, and so on.

But wait, couldn't Drop::drop be special-cased, so that it destroys self regularly? The problem is, it's not necessarily Drop::drop that would be destroying self. Consider:
struct Foo { 
    // ... some fields
}

fn do_something(foo: Foo) {
    // ... some code
    foo;
}

impl Drop for Foo {
    fn drop(self) {
        do_something(self);
    }
}

Here, the drop code for Foo isn't in Drop::drop, it's in do_something.
In this particular example, Drop::drop could call a special version of do_something that doesn't drop Foo. But the general problem is unsolvable. Consider:
struct Foo {
    fun: fn()
}

static FOO: Mutex> = Mutex::new(None);

fn do_something(foo: Foo) {
    let fun = foo.fun;
    FOO.lock().insert(foo);
    fun();
}

impl Drop for Foo {
    fn drop(self) {
        do_something(self);
    }
}

fn do_something_else() {
    FOO.lock().take();
}

fn main() {
    let foo = Foo { fun: do_something_else };
}

Here, the call to main drops foo = Foo { fun: do_something_else }, which calls Drop::drop, which calls do_something, which inserts foo into FOO, then calls do_something_else, which takes foo out of FOO, then drops foo again...infinite recursion. And the static analysis to detect and prevent this is hard to the point of being infeasible (there are possible examples that are more convoluted).

One possible workaround is to implicitly add a boolean in every Drop-implementing type that is set when the instance gets dropped the first time, and dropping when already set regularly destroys the instance. But this goes against Rust's goal to have maximum efficiency and minimum hidden complexity; no other impl block changes a type's structure. Furthermore, this would prevent Drop from being implemented on repr(transparent) types.
Another workaround is to prevent Drop::drop from wholly moving self, only individual fields. In fact, I could see the developers going with instead of &mut self. Nonetheless, it adds complexity to an already complex language, especially the Drop trait which already has extra restrictions.

Meanwhile, Drop::drop taking &mut self isn't a big problem, because it can be worked around in multiple ways:

In safe Rust: by replacing self with dummy data.

#[derive(Default)]
struct Foo {
    // ... some fields implementing `Default`
}

impl Drop for Foo {
    fn drop(&mut self) {
        let this = std::mem::take(self);
        // ... now you have a value `this`
    }
}

If you don't want to implement Default, you can use std::mem::replace and some random values. If a field's type doesn't permit "dummy" instances, you can sacrifice a bit of efficiency and cleanness by wrapping the field in Option, where it will always be Some except in Drop::drop.

In unsafe Rust: by wrapping the type with ManuallyDrop.

struct Foo(ManuallyDrop);

struct FooRepr {
    // ... some fields implementing `Default`
}

impl Foo {
    pub fn new(
        // ... FooRepr fields
    ) -> Self {
        Self(ManuallyDrop::new(FooRepr {
            // ...
        }))
    }
}

impl Deref for Foo {
    type Target = FooRepr;

    fn deref(&self) -> &Self::Target {
        self.0.deref()
    }
}

impl DerefMut for Foo {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.0.deref_mut()
    }
}

impl Drop for Foo {
    fn drop(&mut self) {
        let foo = unsafe { ManuallyDrop::take(&mut self.0) };
    }
}

Also note that, if you only care about moving some of self's fields, you can replace-with-stub or wrap the individual fields instead of the entire value.
> **Comments:**
> **username_5** (2024-07-06): I think this is most likely true, but since the question is about *why the designers chose* this approach it would be ideal to point at some supporting information on that side (which presumably does exist, given the Rust development process).  
> **username_6** (2024-07-06): Swift made `deinit` take `self` as an *im*mutable borrow, because mutating methods are allowed to consume `self` and then assign a new value to it (which would cause `deinit` to recurse). Is this not an issue in Rust?  
> **username_4** (2024-07-08): @Bbrk24 it is possible in Rust with `std::mem::swap`. Likewise, it's possible to get an infinitely-recursing `Drop::drop(&mut self)`, the easiest way just doing `self.clone()` since then the clone will be dropped. But it's not an issue the same way `Drop::drop(self)` is. The thing with `Drop::drop(self)`, is that it would *have* to be special-cased because even an empty function would drop. And then it's not immediately clear what to do when `self` is passed to another function; if that is disallowed, it means the body of `Drop::drop` has special rules that no other function has.  
> **username_4** (2024-07-08): Although `Drop::drop` already has special rules for how its called...  
> **username_4** (2024-07-08): @MichaelHomer other than [a stack exchange post](https://stackoverflow.com/a/30905994) with roughly the same answer, and some Reddit and forum posts asking how to move dropped fields, the only thing I found were the the commits where `drop` was added. It was *really* early in development (before the `Drop` trait, there were `drop { ... }` blocks).  
> **username_4** (2024-07-08): So I finally found this: **https://github.com/rust-lang/rust/issues/2955**. It looks like the idea to let destructors move out fields was proposed in 2012, but it was dropped due to "not adding expressiveness" due to the `Option` (in today's Rust I suspect it would be more like `ManuallyDrop`) workaround.  
> **username_7** (2024-07-09): It’s not that the problem is unsolvable imo, it’s that we already have a decent solution. Infinite recursion like you describe can only be caused by resurrection, which can only be caused by escape. You could add language features to prevent escape of `self`, but it’s surprisingly involved, and `&mut self` already does the right thing. Wrapping the innards of `Drop` types in `ManuallyDrop` is the right solution, though it’d be nice if it were safe and a bit simpler.  
> **username_1** (2024-07-10): Doesn't your example using `std::mem::take` also recurse infinitely? `this` will have to be dropped at the end of the function.  
> **username_4** (2024-07-10): No, because `this.0`/`FooRepr` is being dropped.  
---
