The move: assignment is a transfer of title
Worked examples
Read the claim, then run it and check the machine agrees. One at a time — nothing here is taken on trust.
fn main() {
let s1 = String::from("hello");
let s2 = s1; // ownership moves; s1 is retired at compile time
// println!("{s1}"); // <- uncomment: error[E0382] borrow of moved value
println!("s2 owns it: {s2} (len {})", s2.len());
let a = 5;
let b = a; // i32 is Copy: duplicated, not moved
println!("both fine: a = {a}, b = {b}");
}
The commented line is the whole lesson: put it back and the program
stops existing — E0382 names the move (let s2 = s1), the reason
(String doesn't implement Copy), and the illegal use. The i32
pair underneath shows the other regime: plain bits copy, and both
names stay live. One heap allocation never gets two owners.
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone(); // copies the HEAP bytes, not just the 3 stack words
// both alive, and provably independent storage:
println!("s1 = {s1}, s2 = {s2}");
println!("separate heap allocations: {}", s1.as_ptr() != s2.as_ptr());
println!("a String is {} bytes on the stack", std::mem::size_of::<String>());
}
clone() is the explicit, priced way to get two owners: the pointers
differ (printed: true), so each can be freed independently — no
double-free possible. That's why Rust never clones silently: the
24-byte stack part is cheap to copy, the heap part is not, and the
language makes you say the expensive word out loud.
fn shout(s: String) -> String {
// takes ownership, transforms, RETURNS ownership
s.to_uppercase()
}
fn measure(s: String) -> (String, usize) {
let n = s.len();
(s, n) // hand the string back alongside the answer
}
fn main() {
let name = String::from("ferris");
let loud = shout(name);
// println!("{name}"); // <- E0382: `name` moved into shout()
println!("loud = {loud}");
let (back, n) = measure(loud);
println!("still ours: {back} (len {n})");
}
Calling shout(name) moves name into the function — the commented
line would be E0382 again, same diagnosis, new location. measure
shows the workaround this lesson allows: return the value alongside
the answer. It works, and it's clumsy — you can feel the tuple tax.
Borrowing (&s) dissolves all of it, and that's m03-1.
Check the concept
One question at a time. Unsure? Revisit the lecture, then answer.
The challenge
Pass the quiz to unlock the challenge — your code will still be waiting here.