Ownership

Rust is a systems programming language focused on speed, memory safety, and fearless concurrency — and ownership is the single feature that makes all of that possible without a garbage collector.

Learn Ownership in our free Rust course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Rust course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll learn the three rules of ownership, what it means for a value to be moved, why some types copy instead, and how ownership flows through functions.

What You'll Learn in This Lesson

1️⃣ Moves, Clones, and Copy Types

Every value has exactly one owner . For a heap type like String , assigning it to another variable moves ownership, and the original becomes invalid — this stops two variables from freeing the same memory. If you need two independent copies, call .clone() . Small stack types like i32 implement Copy , so they are duplicated cheaply and both stay valid.

The crucial line is let s2 = s1; — after it, s1 is moved-from and unusable. Contrast that with let y = x; for the integer, where both remain valid because i32 is Copy .

2️⃣ Ownership and Functions

Passing a value to a function follows the same rules. A String argument is moved into the function; afterward the original variable is gone. A Copy type is copied in, leaving the original usable. A function can also return a value, moving ownership back out to the caller.

When takes_ownership ends, its text goes out of scope and is automatically dropped — its heap memory freed, no manual cleanup. This automatic drop at end-of-scope is the third ownership rule in action.

Your turn. Fill in the blanks marked ___ , then run it.

Move a String into a function and get a new one back. Run it with cargo run and check the output.

📋 Quick Reference — Ownership

Practice quiz

How many owners does a value have at one time in Rust?

  • Zero
  • Two
  • Exactly one
  • Unlimited

Answer: Exactly one. Each value has exactly one owner at a time.

After let s2 = s1; for a String, what happens to s1?

  • It is moved and becomes invalid
  • It is copied
  • It is borrowed
  • It stays usable

Answer: It is moved and becomes invalid. Assigning a String moves ownership, leaving s1 invalid.

What does using a moved String afterward cause?

  • A runtime crash
  • A silent copy
  • Nothing
  • A compile error

Answer: A compile error. Using a moved value is a compile-time error (E0382).

How do you make an independent deep copy of a String?

  • .copy()
  • .clone()
  • .dup()
  • .deep()

Answer: .clone(). .clone() deep-copies the heap data so both variables are valid.

Why can you use an i32 after let y = x;?

  • i32 implements Copy
  • i32 is on the heap
  • Integers cannot move
  • x is borrowed

Answer: i32 implements Copy. Small stack types like i32 implement Copy, so both stay valid.

What happens when you pass a String to a function by value?

  • It is borrowed
  • It is cloned
  • It is moved into the function
  • Nothing changes

Answer: It is moved into the function. Passing a String by value moves ownership into the function.

When is a value dropped (its memory freed)?

  • When you call free()
  • When its owner goes out of scope
  • Never
  • At program start

Answer: When its owner goes out of scope. A value is dropped automatically when its owner leaves scope.

How can a function give ownership back to the caller?

  • By cloning
  • By borrowing
  • It cannot
  • By returning the value

Answer: By returning the value. Returning a value moves ownership out to the caller.

Which is often a better fix than cloning to read a value?

  • Copy the whole program
  • Borrow it with &
  • Use unsafe
  • Make it static

Answer: Borrow it with &. If you only need to read, borrow with & instead of cloning or moving.

Does Rust use a garbage collector to free memory?

  • Yes
  • Only in debug
  • No, ownership frees memory at compile-time-known points
  • Only for Strings

Answer: No, ownership frees memory at compile-time-known points. Ownership frees memory deterministically with no garbage collector.