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:
split_at_mut(mid)splits a slice into two non-overlapping mutable halves.swap(i, j)if you just want to exchange two elements.get_disjoint_mut([i, j])(Rust 1.86+) returns mutable references to several distinct indexes, or an error if they overlap or are out of bounds.- Do one at a time:
hp[0] -= 10; hp[1] -= 10;Each borrow ends immediately.
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