🎓 A1Learner
🔍

Rust Ownership

Ownership is the rule that every value in Rust has exactly one owner. The owner decides when the value is cleaned up.

Assignment moves a String

let other = title; moves the text. Only the small handle changes hands. The letters stay put. And title is switched off. So the heap memory can never be freed twice:

let title = String::from("Dune");
let other = title;
// println!("{title}"); // error: title was moved
println!("{other}");

Simple values are copied instead

Whole numbers, bools and chars are Copy types. Both names keep working:

let n = 9;
let m = n;
println!("{n} {m}");

Giving to a function moves it too

take owns its parameter, so gift is given away by the call:

fn take(s: String) {
    println!("took {s}");
}
let gift = String::from("gift");
take(gift);

Clone when you truly need two owners

.clone() makes a full copy — letters and all — so both names own one:

let a = String::from("hey");
let b = a.clone();
println!("{a} {b}");

A tuple copies only if every part copies

(5, true) is all Copy parts, so the whole tuple copies. Swap in a String part and the same line would move instead:

let pair = (5, true);
let copy = pair;
println!("{} {}", pair.0, copy.1);

Mutability lives in the binding

The value itself has no mut setting — the binding does. Move a value into a mut binding and it can change from there:

let name = String::from("ferris");
let mut name = name;
name.push_str("!");
println!("{name}");

Example

fn main() {
    let a = String::from("hello");
    let b = a; // a is MOVED into b
    // println!("{}", a); // would NOT compile
    println!("{}", b);
    let n = 5;
    let m = n; // i32 is Copy
    println!("{} {}", n, m);
}

Key points

  • When the owner goes out of scope, the value is dropped and its memory is freed
  • Giving a variable a brand-new value drops the old value at once.
  • Its memory is freed immediately.
  • It is not freed at the end of the block.
  • A borrowed value is pinned in place.
  • While a reference to it will still be used, the owner cannot move it away.
  • Rust refuses.
  • The error is E0505: cannot move out because it is borrowed.

In this example, a is a String holding "hello". The line let b = a; moves the text to b. From that line on, a is empty-handed. Using a would be a compile error. The code shows this in a comment. The println! uses b, the real owner, and prints hello. Numbers behave differently. n is an i32, a simple Copy type. let m = n; copies the number. So both n and m can be printed: 5 5. Rust moves heap values like String so that two owners can never free the same memory twice.

Note

Many languages free memory with a garbage collector that runs later.

Rust frees memory the moment the owner ends — no collector, and no manual free calls like in C.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

After let b = a; where a is a String, what is true?