# Why mutation of captured by move variable is considered mutation?

**URL:** <https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598>\
**Category:** language design\
**Created:** [March 30, 2023, 6:50pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598 "2023-03-30T18:50:03Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![HKalbasi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hkalbasi/32/7938_2.png) [@HKalbasi](https://internals.rust-lang.org/u/HKalbasi)\
**Post date:** [March 30, 2023, 6:50pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598/1 "2023-03-30T18:50:03Z")

</div>

In this code ([playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8566d6c0cec6bae56a3b1cda2c702823)):

```rust
fn main() {
    let mut x = 2;
    let mut y = move || {
        x += 1;
        x
    };
    let (a, b) = (y(), y());
    println!("{a} {b} {x}");
}

```

`3 4 2` will be printed, which shows that the original `x` is not mutated. But if you remove the `mut` from `let mut x`, you will get an error. Why?

---

<div class="post-metadata">

**Author:** ![rpjohnst](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rpjohnst/32/9524_2.png) [@rpjohnst](https://internals.rust-lang.org/u/rpjohnst)\
**Post date:** [March 30, 2023, 6:56pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598/2 "2023-03-30T18:56:47Z")

</div>

There is no fundamental reason it has to work this way for safety or anything. But there is no other place to mark the capture itself as mutable, so that's how the syntax was designed.

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [March 30, 2023, 7:02pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598/3 "2023-03-30T19:02:28Z")

</div>

Removing the closure and moving the outer variable in by hand gives you:

```rust
let mut x = 2;
x += 1;
x

```

Without the `mut` it's clearly invalid:

```rust
let x = 2;
x += 1;
x

```

---

<div class="post-metadata">

**Author:** ![HKalbasi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hkalbasi/32/7938_2.png) [@HKalbasi](https://internals.rust-lang.org/u/HKalbasi)\
**Post date:** [March 30, 2023, 7:04pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598/4 "2023-03-30T19:04:15Z")

</div>

The `mut` in `let mut y` mark the closure (and so its fields) as mutable. I think forcing `x` to be mutable is misleading and inconsistent with the rest of the language.

---

<div class="post-metadata">

**Author:** ![HKalbasi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hkalbasi/32/7938_2.png) [@HKalbasi](https://internals.rust-lang.org/u/HKalbasi)\
**Post date:** [March 30, 2023, 7:06pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598/5 "2023-03-30T19:06:17Z")

</div>

Removing the closure would work like this:

```rust
let mut x = 2;
let mut closure_state = x;
closure_state += 1;
closure_state

```

Which in it compiler will warn that `mut` can be removed.

---

<div class="post-metadata">

**Author:** ![sahnehaeubchen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sahnehaeubchen/32/9709_2.png) [@sahnehaeubchen](https://internals.rust-lang.org/u/sahnehaeubchen)\
**Post date:** [March 30, 2023, 7:08pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598/6 "2023-03-30T19:08:26Z")

</div>

But what if you want `closure_state_x` to be mutable but `closure_state_y` to be immutable? Currently there is no way to declare a change of mutability upon capture so its just inhereted from the declaration.

---

<div class="post-metadata">

**Author:** ![bascule](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bascule/32/3057_2.png) [@bascule](https://internals.rust-lang.org/u/bascule)\
**Post date:** [March 30, 2023, 7:46pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598/7 "2023-03-30T19:46:23Z")

</div>

> [@HKalbasi](#):
>
> The `mut` in `let mut y` mark the closure (and so its fields) as mutable.

That would make any variable moved from the outer scope instantly mutable, which may not be intended.

Edit: I see @sahnehaeubchen made a similar point. It's nice to be able to have mixed mutable and immutable variables referenced in the closure.

---

<div class="post-metadata">

**Author:** ![cuviper](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cuviper/32/1897_2.png) [@cuviper](https://internals.rust-lang.org/u/cuviper)\
**Post date:** [March 30, 2023, 7:56pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598/8 "2023-03-30T19:56:45Z")

</div>

If you really don't want the outer `x` to be mutable, you can rebind it for the closure:

```rust
fn main() {
    let x = 2;
    let mut y = {
        let mut x = x;
        move || {
            x += 1;
            x
        }
    };
    let (a, b) = (y(), y());
    println!("{a} {b} {x}");
}

```

That technique is also useful when you want to mix some captures moved by value with others by reference -- then you can create explicit references and `move` those instead.

---

<div class="post-metadata">

**Author:** ![marcospb19](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/marcospb19/32/8650_2.png) [@marcospb19](https://internals.rust-lang.org/u/marcospb19)\
**Post date:** [April 5, 2023, 3:29pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598/9 "2023-04-05T15:29:08Z")

</div>

Just to add more:

This rebind technique is also very useful when using `tokio::spawn(async move { t })`, the inner `Future` cannot carry non-static lifetimes, so you need to move everything, and therefore `.clone()` everything.

There are two ways I usually do this:

```rust
let name = self.name.clone();
let rx = self.receiver.clone();

tokio::spawn(async move {
    // Use `name` and `rx`
});

```

and like this (similar to what cuviper showed, cloned in the inner scope):

```rust
tokio::spawn({
    let name = self.name.clone();
    let rx = self.receiver.clone();

    async move {
        // Use `name` and `rx`
    }
});

```

TLDR: if you see `tokio:spawn` (or `Fut: 'static`) prepare to `move`, and if you see `move`, prepare to rebind! :v

---

<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:** [July 4, 2023, 3:29pm UTC](https://internals.rust-lang.org/t/why-mutation-of-captured-by-move-variable-is-considered-mutation/18598/10 "2023-07-04T15:29:44Z")

</div>

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