Core Concepts
Ownership and Borrowing
Understand Rust's unique ownership system — the key to memory safety without garbage collection.
The Ownership System
Rust's most unique feature. Three rules:
- Each value in Rust has a variable called its owner
- There can only be one owner at a time
- When the owner goes out of scope, the value is dropped (memory freed)
Move vs Copy
- Move: When you assign a heap value to another variable, ownership moves. The original is no longer valid.
- Copy: Stack types (integers, booleans, etc.) are copied instead of moved.
Borrowing (References)
References allow you to refer to a value without taking ownership.
&T— immutable reference (many allowed simultaneously)&mut T— mutable reference (only one at a time, no immutable refs)
The Borrow Checker
The compiler enforces these rules at compile time. This is why Rust has no runtime memory errors.
Example
rust
fn main() {
// Ownership and Move
let s1 = String::from("hello");
let s2 = s1; // s1 is MOVED to s2
// println!("{}", s1); // ERROR: s1 no longer valid!
println!("{}", s2); // OK
// Clone to make a deep copy
let s3 = String::from("world");
let s4 = s3.clone(); // explicit deep copy
println!("{} {}", s3, s4); // both valid
// Copy types (stack-allocated)
let x = 5;
let y = x; // x is COPIED, not moved
println!("{} {}", x, y); // both valid
// Borrowing
let s = String::from("hello");
let len = calculate_length(&s); // pass reference
println!("'{}' has {} chars", s, len); // s still valid!
// Mutable borrowing
let mut text = String::from("hello");
change(&mut text);
println!("{}", text); // hello, world
}
fn calculate_length(s: &str) -> usize {
s.len() // just reading, no ownership taken
}
fn change(s: &mut String) {
s.push_str(", world"); // modifying through mutable reference
}
// Lifetime annotations (explicit borrowing lifetimes)
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}Try it yourself — RUST