cannot borrow `*self` as mutable more than once at a time
cannot borrow `*self` as mutable more than once at a time in Rust means rust's borrow checker detected two simultaneous mutable borrows of the same memory location, violating Rust's core aliasing XOR mutability invariant.
How do I fix cannot borrow `*self` as mutable more than once at a time?
To fix cannot borrow `*self` as mutable more than once at a time in Rust, locate the line causing the error and check the values right before it runs. Most occurrences happen because of calling a mutable method while holding a mutable reference to a field. Apply a defensive check or safe fallback, make sure collections or objects exist before access, and verify return values from upstream functions.
What does cannot borrow `*self` as mutable more than once at a time mean?
Rust guarantees thread safety and memory safety by enforcing that data may have either any number of immutable references (&T) OR exactly one mutable reference (&mut T) at any given point in time, but never both.
Why does cannot borrow `*self` as mutable more than once at a time happen?
1. Calling a mutable method while holding a mutable reference to a field
Holding &mut self.field borrows the entire struct &mut self, preventing calls to other &mut self methods.
Breaks
let first = &mut list[0];
list.push(42); // error: list is already borrowed mutably by first!Works
list.push(42);
let first = &mut list[0]; // re-borrow after mutation completes2. Nested iteration over a mutable collection
Iterating with for item in &mut items borrows items for the entire loop duration.
Breaks
for a in &mut vec {
vec.push(*a); // cannot borrow vec as mutable inside its own iterator!
}Works
let clones = vec.clone();
for a in clones {
vec.push(a);
}How to find it in your own code
Scope mutable borrows tightly so they drop before subsequent mutations. Use .clone() or indexing when iterating if you must mutate the container, or use internal mutability types like RefCell<T> or Mutex<T> if concurrent mutation is required.
Try it: fix this bug
mediumMatch arm unconditionally matches because variable name binds a new pattern instead of comparing
fn match_expected_code(actual: i32, expected: i32) -> bool {
match actual {
// 'expected' here binds a new local variable shadowing the parameter!
expected => true,
_ => false,
}
}
fn main() {
println!("{}", match_expected_code(404, 200));
}More challenges with this error
Each of these challenges runs into this error or pattern. Find the bug and fix it in your browser — no install, no account needed.
Still not sure why yours breaks?
Paste it into the visualizer and watch it run line by line, with every variable at every step. Free, and it runs in your browser.