Understanding Ownership and Borrowing in Rust
2025-10-10
If you're starting with Rust, you've probably run into the concepts of ownership, borrowing, and lifetimes - and maybe you've hit a few compiler errors that made your head spin.
Don't worry - you're not alone.
What You'll Learn
- What is Ownership in Rust?
- Move vs Copy
- Borrowing: Immutable & Mutable
- Common errors and how to fix them
- Summary table and mental model
What is Ownership?
Rust uses a unique system called Ownership to manage memory without a garbage collector.
Key rules:
- Each value has a single owner.
- When the owner goes out of scope, the value is dropped.
- Values can be moved or borrowed, but not both at the same time.
Example: Ownership Transfer (Move)
fn main() {
let s1 = String::from("hello");
let s2 = s1;
println!("{}", s1); // Error: value borrowed after move
}
Why the error?
When you do let s2 = s1;, Rust moves the ownership of the heap data to s2. Now s1 is no longer valid.
Fixing it with Borrowing
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("Length of '{}' is {}", s1, len);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
Output:
Length of 'hello' is 5
We passed a reference (&s1) to calculate_length, so ownership is not moved.
Mutable Borrowing
fn main() {
let mut s = String::from("hello");
change(&mut s);
println!("{}", s);
}
fn change(s: &mut String) {
s.push_str(", world");
}
Output:
hello, world
Rust only allows one mutable references at a time to prevent data races.
Visualizing Ownership
+------------------+ +------------------+
| let s1 = ... | ----> | "hello" in heap |
+------------------+ +------------------+
let s2 = s1; // s1 moved to s2
+------------------+ +------------------+
| s2 owns data | ----> | "hello" in heap |
+------------------+ +------------------+
Common Errors
1. Multiple mutable borrows
let r1 = &mut s;
let r2 = &mut s; // error
Fix: Only allow one mutable reference at a time
2. Borrowing after move
let s1 = String::from("hey");
let s2 = s1;
println!("{}", s1); // use of moved value
Fix: Use references or clone if needed
Final Thoughts
Rust’s ownership system can seem strict at first — but it saves you from memory leaks, data races, and null pointer bugs without a garbage collector.
Tip: If you're confused, slow down, read the error message. The Rust compiler is your friend, not your enemy.