Ownership
Ownership in Tuples and Arrays
Tuples (T1, T2, ...) and fixed-size arrays [T; N] own all of their elements directly inline on the stack. How ownership behaves when you index, destructure, or assign a tuple or array depends on whether its element types implement Copy.
Tuples: Element-By-Element Ownership vs Array Indexing
There is a fundamental difference between accessing a tuple field (tuple.0) and indexing an array element (array[i]):
| Operation | Allowed on Non-Copy Elements (e.g., String)? |
Why |
|---|---|---|
Tuple field move (let s = tup.0;) |
Yes! (Performs a partial move of .0 only) |
.0 is a compile-time constant field, so rustc tracks which exact fields of tup have been moved |
Array index move (let s = arr[i];) |
No! (E0508: cannot move out of type '[String; N]') |
i can be an arbitrary runtime usize; the compiler cannot track which array slots are uninitialized at runtime! |
Array pattern destructuring (let [a, b] = arr;) |
Yes! | Moves all elements out of arr simultaneously in a single pattern |
fn main() {
// 1. Moving a single non-Copy element out of a tuple is ALLOWED (partial move):
let tup: (String, i32) = (String::from("moved from tuple"), 42);
let extracted_str = tup.0;
let remaining_int = tup.1; // `tup.1` is still valid!
println!("From tuple: '{extracted_str}' and {remaining_int}");
// 2. Moving all elements out of a non-Copy array via destructuring is ALLOWED:
let arr: [String; 2] = [String::from("first"), String::from("second")];
let [first, second] = arr;
println!("From array destructuring: '{first}' and '{second}'");
}
From tuple: 'moved from tuple' and 42
From array destructuring: 'first' and 'second'
Why Moving Out of an Array by Index [i] Fails (E0508)
Attempting to move a String out of an array using arr[0] fails at compile time because it would leave arr[0] uninitialized while arr[1] is still alive (and when arr goes out of scope, Drop expects every element of [T; N] to be initialized):
// ❌ does not compile
fn main() {
let names = [String::from("Alice"), String::from("Bob")];
let first = names[0];
}
error[E0508]: cannot move out of type `[String; 2]`, a non-copy array
--> src/main.rs:3:17
|
3 | let first = names[0];
| ^^^^^^^^
| |
| cannot move out of here
| move occurs because `names[_]` has type `String`, which does not implement the `Copy` trait
|
help: consider borrowing here
|
3 | let first = &names[0];
| +
error: aborting due to 1 previous error
Extracting One Element from a Non-Copy Array Safely
To extract a single element from [String; N] without cloning:
- Borrow it:
let first: &String = &names[0]; - Swap/take it from a
mutarray:let first: String = std::mem::take(&mut names[0]);(leaves an emptyString::new()innames[0]). - Destructure with
..:let [first, ..] = names;(movesfirstand drops the remaining elements).