Standard Collections

Borrowing Collection Elements

The borrow checker tracks a collection as a single ownership unit: borrowing a single element (&vec[0] or map.get(&k)) borrows the entire collection for the lifetime of that element reference.

Why Borrowing One Element Locks the Collection Against Mutation (E0502)

If you hold a shared reference let first = &vec[0]; and then call vec.push(x), push might exceed vec.capacity(), allocate a new heap buffer, copy the elements over, and free the old buffer—leaving first as a dangling pointer! Rust prevents this at compile time:

first = &vec[0] ──────┐
                      ▼
Old Heap Buffer:  [ 10, 20 ]   <-- If `vec.push(30)` reallocated and freed this,
                                   `first` would dangle!
// ❌ does not compile
fn main() {
    let mut vec = vec![10, 20];
    let first = &vec[0]; // Immutable borrow of `vec` starts here

    vec.push(30);        // Error: mutable borrow of `vec` while `first` is still live

    println!("First: {first}");
}
error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable
 --> src/main.rs:6:5
  |
4 |     let first = &vec[0];
  |                  --- immutable borrow occurs here
5 |
6 |     vec.push(30);
  |     ^^^^^^^^^^^^ mutable borrow occurs here
7 |
8 |     println!("First: {first}");
  |                      ------- immutable borrow later used here

Borrowing Multiple Elements Mutably at the Same Time

Because the compiler's index operator (&mut vec[0] and &mut vec[1]) cannot prove in general that two runtime index expressions i and j are distinct, attempting to take two &mut element references via indexing fails with E0499.

Instead, use dedicated disjoint-borrowing methods on slices and maps:

Method Signature / Target What It Provides
slice.split_at_mut(mid) &mut [T] Two non-overlapping mutable slices (&mut [T], &mut [T]) (..mid and mid..)
slice.split_first_mut() &mut [T] Option<(&mut T, &mut [T])> (first element + remaining tail)
[a, b] slice pattern if let [first, second, ..] = &mut slice[..] Disjoint mutable bindings via slice pattern matching
slice.swap(i, j) &mut [T] Swaps two elements in place without holding two &mut references
fn main() {
    let mut scores = vec![100, 200, 300, 400];

    // 1. Disjoint mutable borrows via slice pattern matching:
    if let [first, second, ..] = &mut scores[..] {
        *first += 10;
        *second += 20;
    }

    // 2. Splitting into two non-overlapping mutable halves with `split_at_mut`:
    let (left, right) = scores.split_at_mut(2);
    left[0] += right[0];

    println!("Updated scores: {scores:?}");
}
Updated scores: [410, 220, 300, 400]