Borrowing rules help Rust keep your data safe by controlling how you use it without making copies.
When you want to let a function use your data without giving up ownership.
When you want to read data from multiple places at the same time safely.
When you want to change data but only from one place at a time.
When you want to avoid making extra copies of large data to save memory.
Syntax
Rust
let reference = &value; // Immutable borrow
let mut_reference = &mut value; // Mutable borrow
Use & to borrow data immutably (read-only).
Use &mut to borrow data mutably (read and write).
Examples
This shows how to borrow a value immutably to read it.
Rust
let x = 5;
let y = &x; // immutable borrowprintln!("{}", y);
This shows how to borrow a value mutably to change it.
Rust
let mut x = 5;
let y = &mut x; // mutable borrow
*y += 1;
println!("{}", x);
You can have many immutable borrows at the same time.
Rust
let x = 10;
let r1 = &x; // immutable borrow
let r2 = &x; // another immutable borrowprintln!("{} and {}", r1, r2);
You cannot have an immutable borrow while a mutable borrow exists.
Rust
let mut x = 10;
let r1 = &mut x; // mutable borrow// let r2 = &x; // error: cannot borrow as immutable while mutable borrow exists
*r1 += 5;
println!("{}", x);
Sample Program
This program shows borrowing rules: multiple immutable borrows can happen together, but mutable borrow must wait until immutable borrows end.
Rust
fn main() {
let mut number = 10;
{
let r1 = &number; // immutable borrow
let r2 = &number; // another immutable borrowprintln!("r1 = {}, r2 = {}", r1, r2);
} // r1 and r2 go out of scope here
let r3 = &mut number; // mutable borrow
*r3 += 5;
println!("number after mutation = {}", number);
}
OutputSuccess
Important Notes
Only one mutable borrow is allowed at a time to avoid conflicts.
Immutable borrows can happen many times simultaneously because they don't change data.
Borrows must always be valid; Rust checks this at compile time to prevent bugs.
Summary
Borrowing lets you use data without taking ownership.
Immutable borrows allow many readers but no writers.
Mutable borrows allow one writer and no readers at the same time.
Practice
(1/5)
1. What does borrowing in Rust allow you to do?
easy
A. Copy data to a new variable
B. Use data without taking ownership
C. Delete data immediately
D. Create multiple owners of data
Solution
Step 1: Understand borrowing concept
Borrowing means using data without taking ownership, so the original owner keeps control.
Step 2: Compare options
Copying or deleting data changes ownership or data state, which borrowing does not do.
Final Answer:
Use data without taking ownership -> Option B
Quick Check:
Borrowing = Use without ownership [OK]
Hint: Borrowing means using data without owning it [OK]
Common Mistakes:
Confusing borrowing with copying
Thinking borrowing deletes data
Assuming borrowing creates multiple owners
2. Which of the following is the correct syntax to create an immutable borrow of a variable x in Rust?
easy
A. let y = &x;
B. let y = *x;
C. let y = &mut x;
D. let y = x;
Solution
Step 1: Identify immutable borrow syntax
Immutable borrow uses &x to create a reference without allowing changes.
Step 2: Check other options
&mut x is mutable borrow, *x dereferences, and x moves ownership.
Final Answer:
let y = &x; -> Option A
Quick Check:
Immutable borrow = &x [OK]
Hint: Immutable borrow uses & before variable [OK]
Common Mistakes:
Using &mut for immutable borrow
Dereferencing instead of borrowing
Assigning ownership instead of reference
3. What will be the output of this Rust code?
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2);
let r3 = &mut s;
println!("{}", r3);
medium
A. hello and hello\nerror at runtime
B. hello and hello\nhello
C. Compile error due to mutable borrow while immutable borrows exist
D. hello\nhello and hello
Solution
Step 1: Analyze immutable borrows
Two immutable borrows r1 and r2 are allowed simultaneously.
Step 2: Check mutable borrow after immutable borrows
Trying to create mutable borrow r3 while immutable borrows exist causes compile error.
Final Answer:
Compile error due to mutable borrow while immutable borrows exist -> Option C
Quick Check:
Mutable borrow disallowed with active immutable borrows [OK]
Hint: No mutable borrow allowed if immutable borrows exist [OK]
Common Mistakes:
Assuming mutable borrow works after immutable borrows
Expecting runtime error instead of compile error
Confusing output with allowed borrows
4. Identify the error in this Rust code snippet:
let mut data = vec![1, 2, 3];
let r1 = &mut data;
let r2 = &data;
r1.push(4);
println!("{:?}", r2);
medium
A. No error, code runs fine
B. Cannot push to vector inside mutable borrow
C. Cannot print vector with {:?}
D. Cannot borrow data as immutable while mutable borrow exists
Solution
Step 1: Check borrows
Variable r1 is a mutable borrow, r2 is an immutable borrow of the same data.
Step 2: Understand borrowing rules
Rust forbids immutable borrow while mutable borrow is active, causing a compile error.
Final Answer:
Cannot borrow data as immutable while mutable borrow exists -> Option D
Quick Check:
Immutable borrow disallowed during mutable borrow [OK]
Hint: No immutable borrow allowed during mutable borrow [OK]
Common Mistakes:
Thinking push is invalid inside mutable borrow
Ignoring borrow conflict between r1 and r2
Assuming printing with {:?} causes error
5. You want to write a function that takes a mutable reference to a vector and appends a number, but also returns the length of the vector after appending. Which function signature and usage follow Rust's borrowing rules correctly?
hard
A. fn add_and_len(v: &mut Vec<i32>, n: i32) -> usize { v.push(n); v.len() }
let mut nums = vec![1,2];
let length = add_and_len(&mut nums, 3);
B. fn add_and_len(v: &Vec<i32>, n: i32) -> usize { v.push(n); v.len() }
let mut nums = vec![1,2];
let length = add_and_len(&nums, 3);
C. fn add_and_len(v: Vec<i32>, n: i32) -> usize { v.push(n); v.len() }
let nums = vec![1,2];
let length = add_and_len(nums, 3);
D. fn add_and_len(v: &mut Vec<i32>, n: i32) -> usize { v.len(); v.push(n) }
let mut nums = vec![1,2];
let length = add_and_len(&mut nums, 3);
Solution
Step 1: Check function signature for mutable borrow
Function needs &mut Vec<i32> to modify vector by pushing a number.
Step 2: Verify function body and usage
fn add_and_len(v: &mut Vec<i32>, n: i32) -> usize { v.push(n); v.len() }
let mut nums = vec![1,2];
let length = add_and_len(&mut nums, 3); pushes number then returns length correctly; usage passes mutable reference.
Step 3: Analyze other options
fn add_and_len(v: &Vec<i32>, n: i32) -> usize { v.push(n); v.len() }
let mut nums = vec![1,2];
let length = add_and_len(&nums, 3); uses immutable borrow but tries to push (not allowed). fn add_and_len(v: Vec<i32>, n: i32) -> usize { v.push(n); v.len() }
let nums = vec![1,2];
let length = add_and_len(nums, 3); takes ownership, not borrow. fn add_and_len(v: &mut Vec<i32>, n: i32) -> usize { v.len(); v.push(n) }
let mut nums = vec![1,2];
let length = add_and_len(&mut nums, 3); returns length before push, so length is old value.
Final Answer:
fn add_and_len(v: &mut Vec<i32>, n: i32) -> usize { v.push(n); v.len() }
let mut nums = vec![1,2];
let length = add_and_len(&mut nums, 3); -> Option A
Quick Check:
Mutable borrow needed to modify vector [OK]
Hint: Use &mut to modify data inside function [OK]
Common Mistakes:
Using immutable borrow when modifying data
Taking ownership instead of borrowing
Returning length before modification
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.