← Debugging Guides

阅读中文版本

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.

intermediatedebuggingrustborrow-checker

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 -30

Interpretation

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);