RustArena

Rust error E0499: cannot borrow as mutable more than once at a time

What E0499 means in Rust, why two &mut references to the same value are forbidden, and fixes like split_at_mut, swap and field borrows.

E0499 means two mutable borrows (&mut) of the same value are alive at the same time. Rust allows only one, because a &mut promises exclusive access: while you hold it, nothing else can read or write that value. That promise is what rules out data races and lets the compiler optimize aggressively.

Two elements of the same Vec

fn main() {
    let mut hp = vec![100, 80];
    let a = &mut hp[0];
    let b = &mut hp[1];
    *a -= 10;
    *b -= 10;
    println!("{hp:?}");
}
error[E0499]: cannot borrow `hp` as mutable more than once at a time
 --> src/main.rs:4:18
  |
3 |     let a = &mut hp[0];
  |                  -- first mutable borrow occurs here
4 |     let b = &mut hp[1];
  |                  ^^ second mutable borrow occurs here
5 |     *a -= 10;
  |     -------- first borrow later used here
  |
  = help: use `.split_at_mut(position)` to obtain two mutable non-overlapping sub-slices

You know hp[0] and hp[1] are different elements, but indexing goes through IndexMut::index_mut(&mut hp, i), which borrows the whole vector. The compiler doesn't reason about index values. Fixes:

Getter methods that return &mut

struct Player {
    health: i32,
    mana: i32,
}

impl Player {
    fn health_mut(&mut self) -> &mut i32 {
        &mut self.health
    }
    fn mana_mut(&mut self) -> &mut i32 {
        &mut self.mana
    }
}

fn main() {
    let mut p = Player { health: 100, mana: 50 };
    let h = p.health_mut();
    let m = p.mana_mut();
    *h -= 10;
    *m -= 5;
}
error[E0499]: cannot borrow `p` as mutable more than once at a time

A method signature &mut self borrows the whole struct, and the returned reference keeps that borrow alive. Borrowing the fields directly works, because the compiler tracks fields separately: let h = &mut p.health; let m = &mut p.mana;. Inside the struct's own methods, prefer working on fields directly, or write one method that does the combined update.

Storing &mut in a loop

Pushing &mut x into a vector inside a loop, or keeping a &mut from one iteration to the next, triggers E0499 because each iteration creates another live mutable borrow. Store indices or owned values instead.

Closures that mutate

A closure that changes a captured variable holds a mutable borrow for as long as the closure exists. Using the variable directly while the closure is still going to be called is E0499 (or E0502 when you only read it). Call the closure for the last time first, or pass the value as a parameter instead of capturing it.

Why not just allow it?

With two &mut to the same Vec, one could push (reallocating) while the other still points into the old buffer. In threads, two writers at once is a data race. Exclusive &mut makes these bugs impossible to compile.

Example

struct Player {
    health: i32,
    mana: i32,
}

fn main() {
    let mut hp = vec![100, 80, 60];

    let (left, right) = hp.split_at_mut(1);
    left[0] -= 10; // left is [100]
    right[1] -= 20; // right is [80, 60]
    println!("after split_at_mut: {hp:?}");

    hp.swap(0, 2);
    println!("after swap: {hp:?}");

    if let Ok([a, b]) = hp.get_disjoint_mut([0, 1]) {
        std::mem::swap(a, b);
    }
    println!("after get_disjoint_mut: {hp:?}");

    let mut p = Player { health: 100, mana: 50 };
    let h = &mut p.health; // borrowing two different fields is fine
    let m = &mut p.mana;
    *h -= 10;
    *m -= 5;
    println!("health {} mana {}", p.health, p.mana);
}

Output:

after split_at_mut: [90, 80, 40]
after swap: [40, 80, 90]
after get_disjoint_mut: [80, 40, 90]
health 90 mana 45

Practice it