Ownership is the first thing that stops people who learn Rust. The compiler rejects code that would run in any other language, and the error messages talk about moves and borrows. The idea behind it is small. Every value lives in exactly one box, and exactly one name holds that box.

The problem ownership solves
A program has to free memory when it no longer needs it. Languages pick one of two ways. C and C++ make you do it by hand, and a mistake is a crash or a security hole. Java, Go and Python use a garbage collector, which is safe and costs time and memory while your program runs.
Rust picks a third way. The compiler works out, before the program runs, where each value stops being used, and it inserts the code to free it there. To do that, it needs rules it can check. Those rules are ownership.
Three rules
- Each value has one owner, which is a variable.
- There is only one owner at a time.
- When the owner goes out of scope, the value is dropped.
That is the whole model. Everything else follows from these three lines.
A move, step by step
Here is the program that surprises everyone.
// file: src/main.rs
fn main() {
let a = String::from("hello");
let b = a;
println!("{}", a); // error: borrow of moved value
}Think of a as a label on a box. The box holds the text. The line let b = a; does not copy the box. It moves the label: the box now belongs to b, and a is an empty name. The compiler refuses to let you read an empty name.
In most languages, both names would point to the same text, and the runtime would work out when to free it. In Rust, there is never a question. The box has one owner, so it is freed exactly once, when b goes out of scope.
A move is not an operation at run time. It is a promise to the compiler that you will not use the old name again.
Lena Fischer
When you want two boxes
If you need two separate copies, say so.
let a = String::from("hello");
let b = a.clone();
println!("{} {}", a, b); // fine: two boxesclone is explicit on purpose. Copying a large string or a vector costs time, and Rust wants that cost to be visible in the code.
Small, simple values are the exception. Integers, floats, booleans and characters live on the stack, and copying them is as cheap as moving them. These types are Copy, and assigning them leaves both names valid.
let x = 5;
let y = x;
println!("{} {}", x, y); // fine: i32 is CopyFunctions take ownership too
Passing a value to a function is a move, exactly like assignment.
fn shout(s: String) {
println!("{}!", s.to_uppercase());
} // s is dropped here
fn main() {
let name = String::from("ferris");
shout(name);
// name is gone: shout owned it and dropped it
}This is the moment most people ask how anyone writes real programs like this. You rarely want a function to take your value away. You want to lend it. That is borrowing, and it is the subject of part two.
Returning gives ownership back
A function can hand ownership to its caller by returning the value.
fn make_greeting(name: &str) -> String {
format!("Hello, {}!", name)
}
let g = make_greeting("world"); // g owns the new StringThe caller is now the owner, and the string lives as long as g does. No garbage collector is involved, and nothing leaks.
Scope and drop
A value is dropped when its owner goes out of scope, which is usually the closing brace.
{
let v = vec![1, 2, 3];
// use v
} // v is dropped, its memory is freedThis is also how Rust closes files, releases locks and shuts network connections. There is no finally block and no defer. The cleanup is tied to the owner, so you cannot forget it.
A mental model that works
When you read Rust, ask one question for each value: who owns this now? If the answer is clear on every line, the code compiles. When the compiler complains, it has found a line where the answer is "nobody" or "two things at once".
| You write | What happens |
|---|---|
let b = a; | The value moves to b. a is no longer usable. |
let b = a.clone(); | A second value is made. Both are usable. |
f(a); | The value moves into f. |
f(&a); | f borrows the value. a stays the owner. |
Does moving a value copy its bytes?
Why is there no garbage collector option?
What comes next
Ownership on its own would make Rust painful. Borrowing is what makes it practical: you lend a value for a short time and get it back, and the compiler checks that the loan is safe. Part two covers references, the one rule that governs them and the lifetime notation that scares people more than it should.