# Negative Drop impls, Drop auto-trait and ImplicitDrop

**URL:** https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267
**Category:** language design
**Created:** [September 2, 2021, 2:23pm UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267 "2021-09-02T14:23:08Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)
#### Post date: [September 2, 2021, 2:23pm UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/1 "2021-09-02T14:23:08Z")

</div>

What meaning we want from this:

```rust
impl !Drop for T {};

```

- Forbid? Unfortunate.
- ...

The `Drop` is implicitly implemented for _all_ types in Rust. Why would it not be an implied trait?

Next, there is wanting of some linear type support in rust, which conflate with `Drop` and panics...

However, we can make an opposite feature: `ImplicitDrop: Drop` trait. It's also implied for all fitiing types, can be opted out via `?ImplicitDrop` bound and a negative impl.  
The types which do such an opt out can still be dropped, except this must happen explicitly (via `drop` or `drop_in_place`).

So at the end we have following situation:

**Do a type implement** `Drop` **?**

1. Yes (explicitly of by compiler's derive)   
**Do a type implement** `ImplicitDrop` **?**
  - Yes (has not opted out)  
**Behaves as today**
  - No  
Cannot go out of scope - must be dropped manually. (but panic still calls `drop` implicitly) (New)

2. No (has a negative `impl`)  
Cannot go out of scope, or be manually dropped =\> needs special care of the programmer. Is a linear type =\> must be used somehow. (New)

To reduce possibilities of misuse, we should say that **any** type which needs destruction should rely on `Drop`.

What do you think?

---

<div class="post-metadata">

### Author: ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)
#### Post date: [September 2, 2021, 2:42pm UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/2 "2021-09-02T14:42:30Z")

</div>

> [@tema2](#):
>
> Next, there is wanting of some linear type support in rust

There’s previous discussion on the topic. One of the most recent probably

> [@Pre-RFC: Leave auto-trait for reliable destruction](https://internals.rust-lang.org/t/pre-rfc-leave-auto-trait-for-reliable-destruction/13825):
>
> EDIT: Proposal Updated - See Updates Summary of updates here: I'm leaving the rest of this post as it is for posterity, so please see the update. TL;DR Define a new auto-trait Leave, which means that the type can be implicitly destroyed when it goes out of scope. Users can declare must-destroy types by through impl !Leave for Foo {}, which are statically guaranteed to be destroyed before their lifetime's upper bound is reached. This super-charges the RAII pattern, which opens up static, zer…

which includes links to more topics, too.

* * *

> [@tema2](#):
>
> The `Drop` is implicitly implemented for _all_ types in Rust.

That’s not quite accurate. The trait `Drop` itself is always _explicit_ when it’s implemented. But types without `Drop` implementations can have so-called “drop glue”, which can (somewhat) be tested with [`mem::needs_drop`](https://doc.rust-lang.org/std/mem/fn.needs_drop.html). The situation as it currently stands also means that `T: Drop` bounds in (generic) Rust code are _always_ useless.

---

<div class="post-metadata">

### Author: ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)
#### Post date: [September 2, 2021, 6:58pm UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/3 "2021-09-02T18:58:11Z")

</div>

> [@steffahn](#):
>
> The situation as it currently stands also means that `T: Drop` bounds in (generic) Rust code are _always_ useless.

And I want it to stay so.

> [@steffahn](#):
>
> The trait `Drop` itself is always _explicit_ when it’s implemented. But types without `Drop` implementations can have so-called “drop glue”

Isn't drop glue also a part of dropping a value? We can do smth.equivalent to this:

```rust
auto trait Drop {
    default fn drop(&mut self) {}; //first we call this
    fn drop_glue(self) {std::intrinstics::drop_glue::<Self>(self)}; //then this; compiler provided
}

```

Then any `Drop` impl will be in fact a specialization.

So now we can properly make `Drop` an **implied** auto trait.

---

<div class="post-metadata">

### Author: ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)
#### Post date: [September 2, 2021, 7:21pm UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/4 "2021-09-02T19:21:23Z")

</div>

At least as it stands currently, the mechanism behind “`auto trait`” does not support anything but marker traits without any methods.

---

<div class="post-metadata">

### Author: ![quinedot](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quinedot/32/7294_2.png) [@quinedot](https://internals.rust-lang.org/u/quinedot)
#### Post date: [September 2, 2021, 9:22pm UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/5 "2021-09-02T21:22:45Z")

</div>

[It has a meaning on nightly](https://github.com/rust-lang/rust/issues/68318) (unratified by RFC as yet).

From [the hackmd](https://hackmd.io/2FYm23s0R-igRnTLaFoo8w):

> With the feature gate `negative_impls` , we now permit negative impls as well as positive ones:
> 
> ```rust
> impl<T: ?Sized> !DerefMut for &T { }
> 
> ```
> 
> Negative impls indicate a semver guarantee that the given trait will not be implemented for the given types.

[See also.](https://github.com/rust-lang/lang-team/issues/96)

---

<div class="post-metadata">

### Author: ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)
#### Post date: [September 2, 2021, 10:12pm UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/6 "2021-09-02T22:12:41Z")

</div>

While this all is also true, my question is more concrete: what if a type will never be implementing `Drop`, how to dispose it then?

e.g do we want drop glue to be a part of `Drop`'s contract? If yes, what to do with `!Drop` types.

If no, do we want it to stay in such a grey, unspecified area, where it is now?

---

<div class="post-metadata">

### Author: ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)
#### Post date: [September 2, 2021, 10:58pm UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/7 "2021-09-02T22:58:57Z")

</div>

It's not really all that complicated a situation currently.

When a value goes out of scope (or you call `ptr::drop_in_place` on it), its drop glue is run. Said drop glue does two things:

- If the type of the value has an implementation of `Drop`, calls `Drop::drop(&mut value)`
- Recursively runs the drop glue of each of the value's fields

(This can actually sometimes lead to a problematic amount of IR bloat sometimes, in that the fields' drop calls are separate inlining candidates rather than one sharable, outlinable group.)

As an optimization, if `mem::needs_drop` returns false, you know that drop glue is recursively guaranteed to be a noöp, and can skip running any drop glue.

* * *

It's important to note that a type doesn't have to implement `Drop` to be disposed of. In fact, any type which implements `Copy` implicitly has a guarantee to never implement `Drop`.

An important part of the `impl !Trait` proposal is that it's not removing anything. All it's doing is saying you'll never `impl Trait`. It would be correct to say that there's `impl<T: Copy> !Drop for T {}` in the standard library.

---

<div class="post-metadata">

### Author: ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)
#### Post date: [September 3, 2021, 2:04am UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/8 "2021-09-03T02:04:51Z")

</div>

> [@tema2](#):
>
> Then any `Drop` impl will be in fact a specialization.

Note that there are a bunch of rules that depend on types _not_ being `Drop`. For example, you can't move out of a field of a type that implements `Drop`, but you _can_ move out of a type which `needs_drop` because of a field but does not have its own `Drop`.

Thus a change like this would be a breaking change.

---

<div class="post-metadata">

### Author: ![felix.s](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/felix.s/32/8073_2.png) [@felix.s](https://internals.rust-lang.org/u/felix.s)
#### Post date: [September 3, 2021, 7:06am UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/9 "2021-09-03T07:06:42Z")

</div>

Personally, I would prefer a proposal that removes the need for negative reasoning about `Drop` entirely, such as the one discussed here:

> [@Fixing the \`Drop\` trait bound](https://internals.rust-lang.org/t/fixing-the-drop-trait-bound/9458):
>
> What would I intuitively expect the Drop trait to behave like: When copying values, there are three categories of types: Cannot be copied (no traits) Can be copied using used-defined code (implements Clone) Can be trivially copied with mem-copy (implements Copy which derives from Clone) For dropping the situation should be similar, with the equivalent categories: Cannot be dropped (linear types). Those currently do not exist in Rust. Can be dropped using user-defined code (implements Drop)…

---

<div class="post-metadata">

### Author: ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)
#### Post date: [September 3, 2021, 1:57pm UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/10 "2021-09-03T13:57:50Z")

</div>

Indeed. The solution is either to add more magic - "is there `Drop` specialization for type or not?" - or to go with trait approach. I think of something like `Dropable` auto trait for drop glue, which `Drop` requires. Opting out from this makes (values of) a type to require programmer attention.

> [@felix.s](#):
>
> I would prefer a proposal that removes the need for negative reasoning about `Drop` entirely

What's the problem with it?

---

<div class="post-metadata">

### Author: ![felix.s](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/felix.s/32/8073_2.png) [@felix.s](https://internals.rust-lang.org/u/felix.s)
#### Post date: [September 6, 2021, 8:58am UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/11 "2021-09-06T08:58:32Z")

</div>

Some of it is explained in the linked thread, but roughly: I think positive-only reasoning better fits conceptually. It allows you to uniformly think of traits as capabilities that _allow_ you to do certain things: right now `Drop` is the only trait that signals _obligation_. Avoiding negative reasoning makes it possible to soundly make a default assumption that a trait is not implemented for a type until proven otherwise.

---

<div class="post-metadata">

### Author: ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)
#### Post date: [December 5, 2021, 8:59am UTC](https://internals.rust-lang.org/t/negative-drop-impls-drop-auto-trait-and-implicitdrop/15267/12 "2021-12-05T08:59:31Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
