Introduction
Moving ownership every time you want to pass data to a function would be tedious - you'd have to keep returning it back. Rust solves this with borrowing: you can create a reference to a value without taking ownership of it. References let functions and code blocks read or modify data temporarily, and the borrow checker enforces rules at compile time that prevent data races and dangling references.
Cricket analogy: Instead of handing the bat outright to a net bowler and waiting for it back, a captain lets a teammate borrow it for a few throws while he keeps official possession, and the coach enforces rules so no two players swing at once.
Syntax
let s = String::from("hello");
let r1: &String = &s; // immutable reference
let len = calculate_length(r1);
let mut m = String::from("hi");
let r2: &mut String = &mut m; // mutable reference
r2.push_str(" there");Explanation
A reference, written with &, lets you 'borrow' a value without owning it - the underlying value is not moved or dropped when the reference goes out of scope. The borrow checker enforces a strict rule: at any given time, you may have either exactly one mutable reference (&mut T) or any number of immutable references (&T) to a piece of data, but never both at once. This prevents data races at compile time, because two simultaneous writers, or a writer and a reader, can never observe inconsistent state. References must also always be valid - Rust rejects any reference that could outlive the data it points to, which eliminates dangling references entirely.
Cricket analogy: A team can field any number of fans watching from the stands (immutable readers), but only one player at a time is allowed to actually bat and change the scoreboard (mutable writer), never both kinds at once.
Example
fn calculate_length(s: &String) -> usize {
s.len() // borrows s, doesn't take ownership
}
fn append_world(s: &mut String) {
s.push_str(" world");
}
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("'{}' has length {}", s1, len); // s1 still valid
let mut s2 = String::from("hello");
append_world(&mut s2);
println!("{}", s2);
// let r1 = &mut s2;
// let r2 = &mut s2; // compile error: second mutable borrow
}Output
'hello' has length 5
hello worldKey Takeaways
- &T creates an immutable reference; &mut T creates a mutable reference.
- You can have many immutable references, or exactly one mutable reference, but never both at the same time.
- References must always point to valid data - dangling references are rejected at compile time.
- Borrowing lets functions use data without taking ownership, so the caller keeps using the value afterward.
- These rules eliminate data races and use-after-free bugs without any runtime checks.
Practice what you learned
1. Which combination of references is allowed simultaneously in safe Rust?
2. What does the borrow checker prevent by disallowing simultaneous mutable and immutable references?
3. What symbol is used to create a mutable reference to a variable named m?
4. What happens if a reference could outlive the data it points to?
5. Does borrowing a value with & take ownership of it?
Was this page helpful?
You May Also Like
Ownership in Rust
Rust's core memory-safety system where every value has exactly one owner and is dropped when that owner goes out of scope.
Lifetimes in Rust
How Rust's lifetime annotations describe how long references remain valid, preventing dangling references at compile time.
Slices in Rust
Slices are references to a contiguous sequence of elements within a collection, letting you view data without owning it.
The String Type in Rust
Rust's owned, growable, heap-allocated String type versus the borrowed &str string slice, and how to build and combine them.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics