Theme
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, orpop; - use
Option::take,mem::take, ormem::replacethrough 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 Tautomatically grants ownership of theT. - Expecting indexing to move a non-
Copyelement out of a collection. - Using
cloneby default when the collection can instead be consumed or updated.
Follow-ups
- Why can
mem::replacemove a value through&mut Tsafely? - How do
Vec::removeandVec::swap_removediffer? - Why can a
Copyelement be read through indexing without a move error?
Related
- Q006. What is the difference between an owner, a binding, a value, and a resource?
- Q016. What is a partial move?
- Q017. How does ownership flow through branches, loops, and conditional initialization?
References
- The Rust Programming Language
- Rust Reference
- Rust Standard Library