Bird
Raised Fist0
Rustprogramming~30 mins

Borrowing rules in Rust - Mini Project: Build & Apply

Choose your learning style10 modes available
Understanding Borrowing Rules in Rust
📖 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

  1. Step 1: Understand borrowing concept

    Borrowing means using data without taking ownership, so the original owner keeps control.
  2. Step 2: Compare options

    Copying or deleting data changes ownership or data state, which borrowing does not do.
  3. Final Answer:

    Use data without taking ownership -> Option B
  4. 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

  1. Step 1: Identify immutable borrow syntax

    Immutable borrow uses &x to create a reference without allowing changes.
  2. Step 2: Check other options

    &mut x is mutable borrow, *x dereferences, and x moves ownership.
  3. Final Answer:

    let y = &x; -> Option A
  4. 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

  1. Step 1: Analyze immutable borrows

    Two immutable borrows r1 and r2 are allowed simultaneously.
  2. Step 2: Check mutable borrow after immutable borrows

    Trying to create mutable borrow r3 while immutable borrows exist causes compile error.
  3. Final Answer:

    Compile error due to mutable borrow while immutable borrows exist -> Option C
  4. 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

  1. Step 1: Check borrows

    Variable r1 is a mutable borrow, r2 is an immutable borrow of the same data.
  2. Step 2: Understand borrowing rules

    Rust forbids immutable borrow while mutable borrow is active, causing a compile error.
  3. Final Answer:

    Cannot borrow data as immutable while mutable borrow exists -> Option D
  4. 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

  1. Step 1: Check function signature for mutable borrow

    Function needs &mut Vec<i32> to modify vector by pushing a number.
  2. 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.
  3. 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.
  4. 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
  5. 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 unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard