Bird
Raised Fist0
Rustprogramming~10 mins

Why borrowing is required in Rust - Visual Breakdown

Choose your learning style10 modes available
Concept Flow - Why borrowing is required
Create variable with data
↓
Pass variable to function
↓
Function needs access to data
↓
Borrow data instead of moving
↓
Function uses borrowed data
↓
Return to caller, original data still valid
↓
Continue using original variable safely
Borrowing lets functions use data without taking ownership, so the original data stays valid after the function finishes.
Execution Sample
Rust
fn print_length(s: &String) {
    println!("Length: {}", s.len());
}

fn main() {
    let text = String::from("hello");
    print_length(&text);
    println!("Text: {}", text);
}
This code shows borrowing a string reference to print its length without moving ownership.
Execution Table
StepActionVariable StatesOwnership/BorrowingOutput
1Create variable 'text' with value "hello"text = "hello"text owns the String
2Call print_length with &text (borrow reference)text = "hello"print_length borrows &text (immutable borrow)
3Inside print_length, access s.len()s = &"hello"Using borrowed referenceLength: 5
4print_length returns, borrow endstext = "hello"Ownership still with text
5Print original text after borrowingtext = "hello"Ownership unchangedText: hello
6End of main, text droppedtext droppedMemory freed
💡 Execution stops after main ends and 'text' is dropped, no ownership moved so no errors.
Variable Tracker
VariableStartAfter Step 2After Step 4Final
textString("hello")String("hello")String("hello")Dropped
sN/A&String("hello") (borrow)N/AN/A
Key Moments - 2 Insights
Why can't we just pass 'text' directly to the function instead of borrowing?
Passing 'text' directly moves ownership to the function, so 'text' can't be used after. Borrowing lets us use it without losing ownership, as shown in execution_table step 2 and 4.
What happens if we try to use 'text' after moving it without borrowing?
The compiler will give an error because 'text' no longer owns the data after move. Borrowing avoids this by only lending access temporarily, as seen in step 5 where 'text' is still usable.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what is the ownership status of 'text' during step 3?
A'text' is borrowed immutably by print_length
B'text' ownership is moved to print_length
C'text' is copied to print_length
D'text' is dropped before print_length
💡 Hint
Check the 'Ownership/Borrowing' column at step 3 in the execution_table.
At which step does the borrow of 'text' end?
AStep 3
BStep 4
CStep 2
DStep 5
💡 Hint
Look for when print_length returns and the borrow ends in the execution_table.
If we passed 'text' without borrowing, what would happen to the ability to print 'text' in step 5?
AWe could still print 'text' normally
B'text' would be copied automatically
C'text' would be moved and not usable, causing a compile error
DThe program would print an empty string
💡 Hint
Refer to key_moments about ownership and borrowing effects on variable usability.
Concept Snapshot
Borrowing in Rust lets functions use data without taking ownership.
Use & to pass a reference.
Ownership stays with original variable.
Prevents data being moved and lost.
Allows safe, temporary access.
Avoids compile errors from moved values.
Full Transcript
This visual trace shows why borrowing is required in Rust. We start by creating a variable 'text' owning a string. When calling a function, we pass a reference to 'text' using & to borrow it. Inside the function, the borrowed reference is used to access data without moving ownership. After the function returns, the original 'text' variable still owns the data and can be used safely. Borrowing prevents ownership transfer, so the data is not lost or invalidated. This avoids errors and allows multiple parts of code to read data safely. The execution table tracks each step, showing ownership and borrowing states, and the variable tracker shows how 'text' and the reference 's' change. Key moments clarify why moving ownership would cause errors and how borrowing solves this. The quiz tests understanding of ownership status during borrowing and consequences of moving data. The snapshot summarizes borrowing as a way to lend access without losing ownership, keeping code safe and error-free.

Practice

(1/5)
1. Why does Rust require borrowing when accessing data instead of always transferring ownership?
easy
A. To allow multiple parts of code to read data without copying it
B. To make the code run slower for safety
C. To force programmers to write more code
D. To prevent any data from being changed

Solution

  1. Step 1: Understand ownership and borrowing

    Ownership means one variable controls the data. Borrowing lets others use data without owning it.
  2. Step 2: Why borrowing is useful

    Borrowing allows multiple parts of code to read data safely without making copies or moving ownership.
  3. Final Answer:

    To allow multiple parts of code to read data without copying it -> Option A
  4. Quick Check:

    Borrowing = safe shared access [OK]
Hint: Borrowing means sharing data without moving ownership [OK]
Common Mistakes:
  • Thinking borrowing slows down code
  • Believing borrowing prevents all data changes
  • Confusing borrowing with copying data
2. Which of the following is the correct syntax to borrow a variable immutably in Rust?
easy
A. let x = ref value;
B. let x = &value;
C. let &x = value;
D. let mut x = &mut value;

Solution

  1. Step 1: Identify borrowing syntax

    In Rust, borrowing immutably uses the ampersand before the variable: &value.
  2. Step 2: Match correct syntax

    The correct way to bind a reference is let x = &value;. Other options are invalid or mean something else.
  3. Final Answer:

    let x = &value; -> Option B
  4. Quick Check:

    Immutable borrow = &value [OK]
Hint: Use & before variable to borrow immutably [OK]
Common Mistakes:
  • Using let x = ref value; invalid syntax
  • Confusing &x with &value
  • Using mutable borrow (&mut) for immutable access
3. What will be the output of this Rust code?
fn main() {
    let s = String::from("hello");
    let r1 = &s;
    let r2 = &s;
    println!("{} and {}", r1, r2);
}
medium
A. hello and hello
B. Compilation error due to multiple mutable borrows
C. hello and error
D. Runtime error

Solution

  1. Step 1: Analyze borrowing in code

    Two immutable references r1 and r2 borrow s simultaneously, which is allowed.
  2. Step 2: Check output of println!

    Both references print the string "hello", so output is "hello and hello".
  3. Final Answer:

    hello and hello -> Option A
  4. Quick Check:

    Multiple immutable borrows print values [OK]
Hint: Multiple immutable borrows allowed, prints values [OK]
Common Mistakes:
  • Thinking multiple immutable borrows cause errors
  • Confusing mutable and immutable borrow rules
  • Expecting runtime errors for borrowing
4. Identify the error in this Rust code and why borrowing is required:
fn main() {
    let mut s = String::from("hello");
    let r1 = &s;
    let r2 = &mut s;
    println!("{} and {}", r1, r2);
}
medium
A. No error, code runs fine
B. Cannot borrow `s` as immutable because it is mutable
C. Cannot borrow `s` as mutable because it is already borrowed as immutable
D. Cannot print two variables in println!

Solution

  1. Step 1: Check borrowing rules

    Rust forbids mutable borrow while immutable borrow exists to prevent data races.
  2. Step 2: Identify error cause

    Here, r1 immutably borrows s, then r2 tries mutable borrow, causing compile error.
  3. Final Answer:

    Cannot borrow `s` as mutable because it is already borrowed as immutable -> Option C
  4. Quick Check:

    Mutable borrow blocked by existing immutable borrow [OK]
Hint: Mutable borrow blocked if immutable borrow exists [OK]
Common Mistakes:
  • Thinking mutable borrow is allowed with immutable borrow
  • Ignoring borrow checker errors
  • Assuming println! causes error
5. You want to write a function that changes a string passed to it without taking ownership. Which borrowing type should you use and why?
hard
A. Immutable borrow (&) because it allows reading the string safely
B. Copy the string inside the function to modify it
C. Ownership transfer because borrowing is not needed for modification
D. Mutable borrow (&mut) because it allows modifying the string without ownership

Solution

  1. Step 1: Understand function parameter needs

    To modify data inside a function without taking ownership, you must borrow it mutably.
  2. Step 2: Choose correct borrow type

    Mutable borrow &mut allows changing the original data safely without moving ownership.
  3. Final Answer:

    Mutable borrow (&mut) because it allows modifying the string without ownership -> Option D
  4. Quick Check:

    Modify data = use &mut borrow [OK]
Hint: Use &mut to change data without ownership transfer [OK]
Common Mistakes:
  • Using immutable borrow when modification is needed
  • Transferring ownership unnecessarily
  • Copying data instead of borrowing
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