C.W.K.
Stream
Lesson 02 of 05 · published

Move Semantics

~12 min · ownership, move, E0382

Level 0Rust Curious
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

Here's the line that breaks every newcomer's mental model — and once it clicks, Rust clicks.

Assignment can move

In most languages, let s2 = s1; either copies the value or makes both names point at the same object. Rust does neither for heap types. It moves: ownership of the heap buffer transfers from s1 to s2, and s1 becomes invalid. Touch s1 afterward and you get the famous error[E0382]: borrow of moved value.

Why move instead of copy?

If both s1 and s2 pointed at the same heap buffer and both tried to free it at scope end, you'd get a double free — a classic C crash. Rust prevents it structurally: after the move, only s2 owns the buffer, so only s2 frees it. There's no scenario where two owners fight over one allocation.

Stack types don't move — they copy

let y = x; where x is an i32 copies the value, because copying a stack scalar is trivial and safe — so x stays valid. The difference isn't arbitrary: types that are cheap and safe to duplicate copy; types that own heap resources move. The next lesson makes that split explicit.

E0382 'use of moved value' is the rite of passage. Everyone hits it. It's not the compiler being difficult — it's catching the exact moment you tried to use something you no longer own. Read it as 'you gave this away two lines ago.'

If you really want two copies

You opt in with .clone() — an explicit, visible deep copy of the heap data. Rust never silently does the expensive thing; if a deep copy happens, you wrote the word clone.

Code

Move, and the error it prevents·rust
fn main() {
    let s1 = String::from("hello");
    let s2 = s1;          // ownership MOVES from s1 to s2

    // println!("{s1}");  // error[E0382]: borrow of moved value: `s1`
    println!("{s2}");     // s2 is the sole owner now — fine

    // Stack scalars copy instead of moving:
    let x = 5;
    let y = x;            // x is COPIED, not moved
    println!("{x} {y}");  // both valid
} // only s2's buffer is freed — no double free possible

External links

Exercise

Write two lines that move a String from one variable to another, then try to print the original. Read the E0382 error. Now make it compile two ways: first with .clone(), then by simply printing the new owner instead. Which one actually allocates more memory?
Hint
.clone() deep-copies the heap buffer; printing the new owner copies nothing. Reach for clone only when you genuinely need two independent copies.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue
💛 by Ttoriwarm

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.