Concept · Rust

Ownership and moves

Every Rust value has exactly one owner; assigning or passing it moves ownership, and the owner's scope decides when it's freed.

3 minmove semanticsDropRAIICopy

Ownership is how Rust frees memory without a garbage collector. Every value has exactly one owner — a variable, a struct field, a slot in a collection — and when that owner goes out of scope, the value is dropped: its destructor runs and its memory is released. The compiler inserts that cleanup at compile time, so there's no runtime tracking and no pause.

Moves

Assigning a value, passing it to a function or returning it moves ownership. The old binding becomes unusable:

rust
let a = String::from("hello");
let b = a;            // ownership moves to b
// println!("{a}");   // error[E0382]: borrow of moved value: `a`
println!("{b}");

A String is a pointer to a heap buffer. If both a and b owned it, both would free it — a double free. A move makes exactly one of them responsible, and the compiler checks every later use.

Small stack-only types such as integers, bool, char and shared references implement Copy, so they're duplicated instead of moved. For heap-owning types, .clone() makes an explicit deep copy when you really need two owners.

Drop is deterministic

Values are dropped at the end of their owner's scope, in reverse order of declaration. Files close, locks unlock and connections return to their pool at a known point, even on early returns. That pattern is called RAII, and it's why Rust needs no defer or finally.

When it bites, and the fixes

  • You want a function to look at a value, not keep it: pass a reference instead. See the borrow checker.
  • Several parts of the program genuinely co-own something: use Rc or Arc (shared ownership by reference counting).
  • You need a second independent value: clone() it, and accept the copy cost.

The ownership lesson walks through moves, Copy, Clone and Drop with exercises.

Learn it in depth