📖 Scenario: You are building a simple Rust program to manage a book's title. You will learn how to use borrowing rules to safely access and modify data without taking ownership.
🎯 Goal: Build a Rust program that creates a book title, borrows it immutably to print, then borrows it mutably to change the title, and finally prints the updated title.
📋 What You'll Learn
Create a variable called book_title with the exact value "The Rust Book".
Create an immutable reference called title_ref that borrows book_title.
Create a mutable reference called title_mut_ref that borrows book_title mutably.
Use println! to print the borrowed title before and after modification.
💡 Why This Matters
🌍 Real World
Borrowing rules help Rust programs manage memory safely without crashes or bugs. This is important in real-world software like web servers, games, and embedded devices.
💼 Career
Understanding borrowing is essential for Rust developers to write safe and efficient code, a key skill for jobs in systems programming and performance-critical applications.
Progress0 / 4 steps
1
Create the initial book title
Create a variable called book_title and set it to the string "The Rust Book".
Rust
Hint
Use let mut book_title = String::from("The Rust Book") to create a mutable string variable.
2
Create an immutable reference to the book title
Create an immutable reference called title_ref that borrows book_title immutably.
Rust
Hint
Use let title_ref = &book_title; to create an immutable borrow.
3
Create a mutable reference to the book title
Create a mutable reference called title_mut_ref that borrows book_title mutably.
Rust
Hint
Use let title_mut_ref = &mut book_title; to create a mutable borrow.
4
Print and modify the book title using references
Use println! to print the book title using title_ref. Then use title_mut_ref to change the title to "The Advanced Rust Book". Finally, print the updated title using title_mut_ref.
Rust
Hint
Use println!("Original title: {}", title_ref); to print the original title. Change the title with *title_mut_ref = String::from("The Advanced Rust Book"); Print the updated title with println!("Updated title: {}", title_mut_ref);.
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.