Skip to content

Q018. Why can't you move a value out of borrowed or indexed content?

Short Answer

Moving requires ownership of the source place. A shared or mutable borrow grants temporary access, not permission to leave the owner's value uninitialized. Indexing a collection also accesses an element through Index or IndexMut, effectively through a reference, and cannot leave an untracked hole. Use borrowing, cloning, consuming iteration, remove, or replacement APIs instead.

Deep Dive

Given &T or &mut T, the referent must remain a valid T when the borrow ends. Moving a non-Copy field or value through that reference would leave the original owner with invalid storage. A mutable borrow permits mutation, but replacement must install another valid value.

Indexing has a related constraint. collection[index] uses indexing traits that provide reference-based access. Moving a non-Copy element directly would require changing the collection's structural state and cleanup obligations without using its API.

Common alternatives are:

  • borrow the value with &collection[index];
  • clone when independent duplication is intended;
  • consume the collection with into_iter;
  • use remove, swap_remove, or pop;
  • use Option::take, mem::take, or mem::replace through mutable access.

Internal Model

Move analysis permits moving only from places for which the operation can transfer ownership while preserving the validity of every remaining owner. Dereferences of borrowed references and indexing expressions do not provide that ownership.

Replacement APIs work because they return the old value while writing a valid replacement or updating the container's length and drop state in a controlled operation.

Example

rust
fn main() {
    let names = vec![String::from("Ada"), String::from("Grace")];

    let borrowed = &names[0];
    println!("{borrowed}");

    // let first = names[0]; // error: cannot move out of indexed content

    let first = names.into_iter().next().unwrap();
    println!("{first}");
}

Common Mistakes

  • Thinking &mut T automatically grants ownership of the T.
  • Expecting indexing to move a non-Copy element out of a collection.
  • Using clone by default when the collection can instead be consumed or updated.

Follow-ups

  • Why can mem::replace move a value through &mut T safely?
  • How do Vec::remove and Vec::swap_remove differ?
  • Why can a Copy element be read through indexing without a move error?

References

  • The Rust Programming Language
  • Rust Reference
  • Rust Standard Library