Skip to content

/glossary/rust/ownership

What is ownership in Rust?

verified onenvironmentlocal · linux 6.18.44-fc-v180 x64 · GNU bash 5.2.21 · rustc 1.97.0 (2d8144b78 2026-07-07)updated
tool
Rust
versions
Rust 1.x
os
any

Ownership is the set of rules Rust uses to manage memory without a garbage collector: every value has exactly one owner, there can be only one owner at a time, and the value is dropped when its owner goes out of scope. Assigning or passing a value that is not Copy moves ownership, and the old variable can no longer be used.

The three rules

  1. Each value in Rust has an owner, the variable that holds it.
  2. There is one owner at a time.
  3. When the owner goes out of scope, the value is dropped and its memory is freed.

These come from the Rust Book chapter on ownership and are checked by the compiler, so a mistake is a compile error and not a crash at run time.

Moves and the error they produce

let t = s; with a String does not copy the text. It moves ownership from s to t, because a String owns heap memory and two owners would free it twice. Using s afterwards is rejected:

bash
printf 'fn main() {\n    let s = String::from("hi");\n    let t = s;\n    println!("{s} {t}");\n}\n' > o.rs
rustc o.rs 2>&1 | sed -n 1,14p
exit ${PIPESTATUS[0]}

Output · exit 1

error[E0382]: borrow of moved value: `s`
 --> o.rs:4:16
  |
2 |     let s = String::from("hi");
  |         - move occurs because `s` has type `String`, which does not implement the `Copy` trait
3 |     let t = s;
  |             - value moved here
4 |     println!("{s} {t}");
  |                ^ value borrowed here after move
  |
help: consider cloning the value if the performance cost is acceptable
  |
3 |     let t = s.clone();
  |              ++++++++

The compiler marks where the value was moved and, for this case, suggests s.clone(). The full explanation is on the page for borrow of moved value.

Move, copy, borrow and clone

OperationSyntaxEffect on the original
Movelet t = s;The original is unusable. This is the default for types that own heap data, such as String and Vec.
Copylet b = a; (integer)Both stay usable. Types that implement the Copy trait are duplicated bit for bit.
Clonelet t = s.clone();A new, independent value is created, which can allocate. The original stays usable.
Shared borrowlet r = &s;Any number of readers at once. The owner keeps ownership and cannot be mutated while the borrow is alive.
Mutable borrowlet r = &mut s;One writer and no readers at the same time. See [cannot borrow as mutable](/errors/rust/e0502-cannot-borrow-as-mutable-because-also-borrowed-as-immutable/).

A Copy type cannot also implement Drop, which is why only plain-data types are copied. A function parameter is a new owner: fn consume(s: String) takes ownership, while fn read(s: &str) borrows. The difference between those two string types is covered in String vs &str.

When the value is dropped

A value is dropped when its owner goes out of scope, in reverse order of declaration. A moved-from variable is not dropped a second time; the new owner is responsible. You can end ownership early with drop(value), which takes ownership and lets it go out of scope immediately.

Practical advice

  • Prefer borrowing in function signatures unless the function must keep the value.
  • Use clone() on purpose, not to silence an error you do not understand, because it can copy large data.
  • Return values instead of mutating through references when that keeps the code simpler.
  • Read the compiler's note: it names the variable, the line of the move and often the fix.

FAQ

What is the difference between a move and a copy in Rust?

A move transfers ownership and the old variable can no longer be used. A copy duplicates the value and both stay usable. Types that implement the Copy trait, such as integers, bool and char, are copied on assignment. String and Vec are moved.

How do I use a value after passing it to a function?

Pass a reference with & so the function borrows it, call clone() to give the function its own copy, or have the function return the value. Borrowing is the cheapest choice and clone() the most direct one when a second owner is really needed.

When does Rust free memory?

When the owner goes out of scope, Rust calls drop on the value, which frees the memory and any other resource it holds. There is no garbage collector, and the point of the free is known at compile time.

Sources