Rust — E0502 cannot borrow as mutable because it is also borrowed as immutable
Resolve E0502 borrow conflicts by shortening immutable borrows and restructuring to avoid overlapping borrows.
Symptoms
- error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
- The error appears when mutating a collection while holding a reference into it
- Adding a read before a write triggers it
- The borrow is no longer used but still in scope
Possible causes
- An immutable reference is still live when a mutable borrow is taken
- A borrow spans a loop that mutates the same collection
- A method takes &self while the caller needs &mut self
- Non-lexical lifetimes cannot end the borrow because the reference is used later
Diagnosis steps
Read the two borrow locations
cargo build 2>&1 | head -30Interpretation
The compiler prints where the immutable borrow is created and where the mutable borrow conflicts, showing the overlap.
Scope the borrow or clone the value
let n = v[0]; v.push(n);Interpretation
Copying the needed value ends the immutable borrow before the mutation, removing the overlap.
Split the data or use indices
let (a, b) = v.split_at_mut(1);Interpretation
Splitting borrows or using indices lets distinct parts be borrowed mutably at once.
Root cause
Two borrows of the same value overlapped: a mutable borrow was requested while an immutable borrow was still live, which the borrow checker forbids to prevent aliasing and mutation at once.
Fix
End the immutable borrow before mutating by copying the value or scoping the reference, restructure to avoid overlapping borrows, or use split_at_mut and indices to borrow disjoint parts.
Verify the fix
Rebuild and confirm the borrow error is gone, then run the tests to confirm the restructured code still produces the intended result.
Symptom walkthrough
The compiler reports E0502, saying a value cannot be borrowed as mutable because it is also borrowed as immutable. The two borrow locations show an overlap where a reference held for reading is still live when the code tries to mutate the same value. Non-lexical lifetimes end many such borrows automatically, so the error means the reference is genuinely used later.
Fix in practice
Stop the immutable borrow before mutating: copy or clone the needed value, scope the reference in a block, or restructure so the read completes first. When you need to mutate distinct parts at once, use split_at_mut or index-based access so the borrows do not conflict.
Verification
Rebuild and confirm the error is gone, then run the tests to confirm the restructuring preserved behavior. A clean build with passing tests confirms the borrows no longer overlap.
Diagnostic commands
Check the behavior with commands like these:
cargo build 2>&1 | head -30
let n = v[0]; v.push(n);
let (a, b) = v.split_at_mut(1);