# \`deinit\` proposal

**URL:** <https://forum.modular.com/t/deinit-proposal/2095>\
**Category:** Language Design\
**Tags:** discussion\
**Created:** [August 7, 2025, 8:27pm UTC](https://forum.modular.com/t/deinit-proposal/2095 "2025-08-07T20:27:26Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [August 7, 2025, 8:27pm UTC](https://forum.modular.com/t/deinit-proposal/2095/1 "2025-08-07T20:27:26Z")

</div>

Discussion thread for the [deinit](https://github.com/modular/modular/blob/94508152d499175c8a9310799ac7406731c5bc64/mojo/proposals/deinit-arg-convention.md) proposal.

cc @clattner as proposal author

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [August 7, 2025, 9:31pm UTC](https://forum.modular.com/t/deinit-proposal/2095/2 "2025-08-07T21:31:23Z")

</div>

I like everything up to `Step 3: Restrict usage of the deinit convention`. However, I think that making it so that you can’t have one type `deinit` another is going to restrict some of the use-cases for linear types, such as compile-time refcounting were you want to `deinit` your “sub-handle” to the type using some sort of main handle which is actually responsible for the destruction. Other places where I could see something like this are for allocators with pointer types designed to force you to “free” the pointer into the correct arena, where this makes it impossible to batch-deallocate objects without some annoying workarounds such as doing a typestate transformation on all of them, which may require a buffer to move them into as part of the transformation.

One other consideration is whether this unnecessarily restricts various forms of the typestate pattern, for instance if you wished to prove that two independent things had happened, the methods which cause them to happen could return linear-type “proof tokens” and require you to pass in some number of them to prove that prior events happened. As an ML-flavored example, you might want to use them to prove that 4 GPUs exist in order to construct a 4-GPU model pipeline, requiring 4 differently-typed tokens.

---

<div class="post-metadata">

**Author:** ![gryznar](https://avatars.discourse-cdn.com/v4/letter/g/e5b9ba/32.png) [@gryznar](https://forum.modular.com/u/gryznar)\
**Post date:** [August 7, 2025, 9:46pm UTC](https://forum.modular.com/t/deinit-proposal/2095/3 "2025-08-07T21:46:19Z")

</div>

I prefer keyword `del` for argument convention. Looks straightforward and self-explanatory:

```mojo
struct Foo:
  fn __del__ (del self): ...

```

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [August 7, 2025, 9:52pm UTC](https://forum.modular.com/t/deinit-proposal/2095/4 "2025-08-07T21:52:03Z")

</div>

+1 for `del` as the name of the argument convention. It is concise and denotes the argument that will be deleted eventually.

```mojo
fn __moveinit__ (out self, del existing: Self):

```

---

<div class="post-metadata">

**Author:** ![Nick](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/nick/32/115_2.png) [@Nick](https://forum.modular.com/u/Nick)\
**Post date:** [August 8, 2025, 5:06am UTC](https://forum.modular.com/t/deinit-proposal/2095/5 "2025-08-08T05:06:17Z")

</div>

I think the proposed design for `deinit` would be a mistake. Whether a function _directly_ or _indirectly_ destroys a value is an implementation detail, and should not be part of the function’s signature. The user of the function doesn’t need to know the difference between var and deinit, and putting this information in the public API of Mojo libraries is probably going to cause unnecessary confusion. Mojo learners will see “deinit” in function signatures and be confused about what it means, when ultimately, from the user’s perspective, it has identical semantics to “var”.

I think the alternative Chris listed at the end of his proposal is the right one: give ` __disable_del` a better name, and require `__ del __` and `__ moveinit__` to invoke it explicitly. This makes the “final deinitialization step” for a value an implementation detail, and therefore frees people from needing to think about it!

Final note: The proposal mentions that `var` should be used instead of `deinit` in function types. This is further evidence that `deinit` should not appear in a function’s signature. The type checker doesn’t care about deinit vs var, and the programmers that are using the function shouldn’t need to care either.

---

<div class="post-metadata">

**Author:** ![akneni](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/akneni/32/26_2.png) [@akneni](https://forum.modular.com/u/akneni)\
**Post date:** [August 8, 2025, 5:13am UTC](https://forum.modular.com/t/deinit-proposal/2095/6 "2025-08-08T05:13:08Z")

</div>

The proposal mentions that `var` should be used instead of `deinit` in function types.

I do have a small concern about this. This means that I can pass the function `fn foo(deinit x): #...`to a parameter that expects `fn foo(var x)`. Even if this works since both functions have the same signatures, this is still a little unintuitive as I would (and did) assume initially that their signatures would be distinct.

I do also see `__disable_del` as a little bit of a foot gun too. I’m not necessarily for or against this proposal; I’m just pointing out something that should be taken into consideration.

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [August 8, 2025, 5:39am UTC](https://forum.modular.com/t/deinit-proposal/2095/7 "2025-08-08T05:39:27Z")

</div>

> Final note: The proposal mentions that `var` should be used instead of `deinit` in function types. This is further evidence that `deinit` should not appear in a function’s signature.

I agree. This might make explaining argument conventions more difficult than before.

In this case I would opt to stick with `__disable_del` but require it to be invoked explicitly: just remove the magic. How about renaming it to `del`?

```auto
struct String:
    ...
    fn __del__ (var self):
        """Destroy the string data."""
        self._drop_ref()
        del self

    fn __moveinit__ (out self, var existing: Self):
        ...
        del existing

```

---

<div class="post-metadata">

**Author:** ![Nick](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/nick/32/115_2.png) [@Nick](https://forum.modular.com/u/Nick)\
**Post date:** [August 8, 2025, 7:01am UTC](https://forum.modular.com/t/deinit-proposal/2095/8 "2025-08-08T07:01:29Z")

</div>

@christoph_schlumpf I think the solution you’ve proposed would be fantastic. It’s simple, and it keeps the function signature as `var`, which is what we want.

I’m not sure whether it makes sense to use the keyword `del`, because we’re discussing an unsafe/restricted feature (marking a struct instance as deleted), whereas in Python `del` is a safe feature that anybody can invoke at any time.

Also, I think Mojo is currently using `del` to mean “invoke the destructor on this particular line”. `del x` is sugar for `x. __del__ ()`

In summary: Your code snippet is very compelling; but we might need to use a different keyword.

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [August 8, 2025, 7:15am UTC](https://forum.modular.com/t/deinit-proposal/2095/9 "2025-08-08T07:15:31Z")

</div>

> [@Nick](#):
>
> In summary: Your code snippet is very compelling; but we might need to use a different keyword.

I did a scan on the modular repo and did not find any usage of `del` in `.mojo` files. But if the name should better indicate that it is a restricted unsafe feature a different name might be better. `__del`?

```auto
struct String:
    ...
    fn __del__ (var self):
        """Destroy the string data."""
        self._drop_ref()
        __del self

    fn __moveinit__ (out self, var existing: Self):
        ...
        __del existing

```

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [August 8, 2025, 7:41am UTC](https://forum.modular.com/t/deinit-proposal/2095/10 "2025-08-08T07:41:47Z")

</div>

For linear types this feature will be used quite often and I thought `del` is the closest to Phyton `del` for Mojo structs. But I see that `del` has additional/different semantics in Phyton that Mojo maybe wants to support in the future like deleting items from a list (` __delitem__ `).

Python:

```python
numbers = [1, 2, 3, 4, 5]
del numbers[2]
numbers # [1, 2, 4]

```

So `del` might not be a good choice if this is the case. ` __mark_del` or just `__ del` then?

---

<div class="post-metadata">

**Author:** ![ivellapillil](https://avatars.discourse-cdn.com/v4/letter/i/eada6e/32.png) [@ivellapillil](https://forum.modular.com/u/ivellapillil)\
**Post date:** [August 8, 2025, 8:51am UTC](https://forum.modular.com/t/deinit-proposal/2095/11 "2025-08-08T08:51:12Z")

</div>

I think if we require the devs to explicitly call \_\_disable\_del on some of the methods, it is no longer an implementation detail of free choice. Having it in function signature also documents what happens to the passed variable which i would see as a positive..

BTW another term we could use instead of `del` is``destroy`. But then it is inconsistent with many places we use del..

---

<div class="post-metadata">

**Author:** ![gryznar](https://avatars.discourse-cdn.com/v4/letter/g/e5b9ba/32.png) [@gryznar](https://forum.modular.com/u/gryznar)\
**Post date:** [August 8, 2025, 8:56am UTC](https://forum.modular.com/t/deinit-proposal/2095/12 "2025-08-08T08:56:58Z")

</div>

Should this be taken into account? I think no, as in both Python and Mojo `del` will denote deleting object

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [August 8, 2025, 9:11am UTC](https://forum.modular.com/t/deinit-proposal/2095/13 "2025-08-08T09:11:41Z")

</div>

I‘m not a Python expert. But if it‘s semantically and compiler side possible `del` would be ideal in Mojo IMO.

---

<div class="post-metadata">

**Author:** ![rd4com](https://avatars.discourse-cdn.com/v4/letter/r/cdc98d/32.png) [@rd4com](https://forum.modular.com/u/rd4com)\
**Post date:** [August 8, 2025, 9:52am UTC](https://forum.modular.com/t/deinit-proposal/2095/15 "2025-08-08T09:52:22Z")

</div>

Yes, using arg convention is making `__disable_del` more like an interface,  
so that isolation of change is pretty useful!  
Also, this makes it structured and a part of something,  
which can be used for logic.

---

<div class="post-metadata">

**Author:** ![samufi](https://avatars.discourse-cdn.com/v4/letter/s/d2c977/32.png) [@samufi](https://forum.modular.com/u/samufi)\
**Post date:** [August 8, 2025, 11:42am UTC](https://forum.modular.com/t/deinit-proposal/2095/16 "2025-08-08T11:42:28Z")

</div>

I see the point that specifying the disable del in the signature seems to be irrelevant for librabry user sand may cause inconsistency as ``var` and `deinint``may be used interchangeably at some places.

However, I think in some cases `deinit does convey important information to the user, as it communicates “there is a custom desctruction implemented here”, which is important, since the custom behaviour may diverge from the otherwise implemented __del__. That means, I cannot rely on the things put in __del__ ` to be executed even though the type may be properly destroyed.

I would like to thorugh in some alternatives, not being convinved of them myself, but maybe they help in the further discussion. Often they would require some extra work to actually make proper sense. The main idea is to add another modifier to `var`, defined to be ignored at the places where `var and deinint could be used interchangeably:`

1. **Version with two key words** :

```mojo
fn fun(var del argument):
    ...

```

1. **Version with joint key word** (communicates that this is a version of var even though this is distinct from `var`:

```mojo
fn fun(var_del argument):
    ...

```

1. **Version with destructor specified in square brackets** (may clash with origins, but there are also some similarities, e.g. “who is responsible for destroying this”. Maybe one could work out a consistent interpreation of `var[…] and ref[...]`):

```mojo
fn fun(var[] argument): # no destructor specified, so no del
    ...
fn fun_alternative(var[None] argument): # no destructor specified, so no del
    ...
fn fun_default(var[argument. __del__] argument): # default, same as no square brackets
    ...

```

1. b) The object responsible for destruction (calling the destructor if it goes out of scope) in curly braces (we may disallow anything except the two given options and raise an incompatible origin error…):

```mojo
fn fun(var[] argument): # no instance marking that the destructor is called when it is out of scope is specified, so no del
    ...
fn fun_alternative(var[None] argument): # same as above
    ...
fn fun_default(var[argument] argument): # default, same as no square brackets
    ...

```

1. **Version with decorator** (not sure if this matches the proper decorator syntax; I think in Python it would not…):

```mojo
@no_destroy(argument)
fn fun(var argument): # no destructor specified, so no del
    ...

```

Maybe we could find a solution along those lines… I think I like the idea of designing something in the direction of origins, i.e., option 3b.

---

<div class="post-metadata">

**Author:** ![samufi](https://avatars.discourse-cdn.com/v4/letter/s/d2c977/32.png) [@samufi](https://forum.modular.com/u/samufi)\
**Post date:** [August 8, 2025, 11:51am UTC](https://forum.modular.com/t/deinit-proposal/2095/17 "2025-08-08T11:51:40Z")

</div>

Btw. if we stick to using some kind of `__disable_del, I would prefer something like mark_as_destroyed(arg), as this is seems more like a proper function rather than a modifier to compiler behaviour (though it might in fact be the latter). I simply think it reduces the load of special syntax.`

---

<div class="post-metadata">

**Author:** ![samufi](https://avatars.discourse-cdn.com/v4/letter/s/d2c977/32.png) [@samufi](https://forum.modular.com/u/samufi)\
**Post date:** [August 8, 2025, 11:58am UTC](https://forum.modular.com/t/deinit-proposal/2095/18 "2025-08-08T11:58:01Z")

</div>

Re: ` __del`: Shouldn’t it be `__ no_del`? It _ **dis** _ables the destructor…

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [August 8, 2025, 1:35pm UTC](https://forum.modular.com/t/deinit-proposal/2095/19 "2025-08-08T13:35:20Z")

</div>

> [@samufi](#):
>
> However, I think in some cases `deinit does convey important information to the user, as it communicates “there is a custom desctruction implemented here”, which is important, since the custom behaviour may diverge from the otherwise implemented __del__. That means, I cannot rely on the things put in __del__ ` to be executed even though the type may be properly destroyed.

Unfortunately this is not the case as `deinit` would only be allowed for functions that directly destroy the argument. Therefore it is an internal implementation artefact that would change if the function calls another function that does the destruction. It would not show up in the function type declaration too. So the user will still not know from the function signatur if the argument will be destroyed eventually. A decorator would have the same issue. The same holds for functions that conditionally destroy the argument. Those functions too would have to use the `var` argument convention.

---

<div class="post-metadata">

**Author:** ![christoph\_schlumpf](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/christoph_schlumpf/32/274_2.png) [@christoph\_schlumpf](https://forum.modular.com/u/christoph_schlumpf)\
**Post date:** [August 8, 2025, 1:41pm UTC](https://forum.modular.com/t/deinit-proposal/2095/20 "2025-08-08T13:41:27Z")

</div>

> Re: ` __del`: Shouldn’t it be `__ no_del`? It _ **dis** _ables the destructor

True. But from the viewpoint of the implementer and caller of the function `__del value` indicates that the `value` will be **del** eted eventually (by allowing the function to destroy the `value` internals and postponing the immediate deletion of the whole `value`).

---

<div class="post-metadata">

**Author:** ![melodyogonna](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/melodyogonna/32/33_2.png) [@melodyogonna](https://forum.modular.com/u/melodyogonna)\
**Post date:** [August 8, 2025, 2:35pm UTC](https://forum.modular.com/t/deinit-proposal/2095/21 "2025-08-08T14:35:45Z")

</div>

Would an unsafe opt-out of the restriction work here?

[Next page](https://forum.modular.com/t/deinit-proposal/2095.md?page=2)
