📖 Scenario: Imagine you have a box that you want to share with your friends. Sometimes, you want to let one friend change what's inside the box, but other times, many friends can look inside without changing it. Rust's RefCell helps you do this safely at runtime.
🎯 Goal: You will create a simple Rust program using RefCell to hold a number. You will learn how to borrow it immutably (to read) and mutably (to change) safely.
📋 What You'll Learn
Create a RefCell holding an integer value
Borrow the value immutably to print it
Borrow the value mutably to change it
Print the changed value
💡 Why This Matters
🌍 Real World
RefCell is useful when you want to change data inside something that is normally immutable, like inside shared objects or GUI state.
💼 Career
Understanding RefCell helps you write safe Rust code that needs interior mutability, common in systems programming and application development.
Progress0 / 4 steps
1
Create a RefCell holding the number 10
Write a line to create a variable called value that is a RefCell holding the integer 10. Use std::cell::RefCell.
Rust
Hint
Use RefCell::new(10) to create the RefCell.
2
Borrow the value immutably to print it
Add a line to borrow value immutably using borrow() and print the number inside with println!. Use val as the variable name for the borrowed reference.
Rust
Hint
Use value.borrow() to get an immutable reference, then print with println!("Value is: {}", *val).
3
Borrow the value mutably to change it
Add code to borrow value mutably using borrow_mut() and change the number inside to 20. Use val_mut as the variable name for the mutable borrow.
Rust
Hint
Use value.borrow_mut() to get a mutable reference, then assign 20 to *val_mut.
4
Print the changed value
Add a line to borrow value immutably again and print the updated number with println!. Use val as the variable name for the borrowed reference.
Rust
Hint
Borrow immutably again with value.borrow() and print the new value.
Practice
(1/5)
1. What is the main purpose of RefCell in Rust?
easy
A. To enable safe sharing of data across multiple threads
B. To enforce borrowing rules at compile time
C. To replace all uses of Box for heap allocation
D. To allow mutation of data even when the data is borrowed immutably
Solution
Step 1: Understand RefCell's role
RefCell allows mutation of data even when it is borrowed immutably by enforcing borrowing rules at runtime.
Step 2: Compare with other options
RefCell is not for multi-threading (that's for Mutex or RwLock), nor does it replace Box or enforce compile-time checks.
Final Answer:
To allow mutation of data even when the data is borrowed immutably -> Option D
Quick Check:
RefCell enables interior mutability = B [OK]
Hint: RefCell allows changing data inside immutable references [OK]
Common Mistakes:
Confusing RefCell with thread-safe types
Thinking RefCell enforces compile-time checks
Assuming RefCell replaces Box for heap allocation
2. Which of the following is the correct way to create a RefCell containing an integer value 10?
easy
A. let x = RefCell::create(10);
B. let x = RefCell(10);
C. let x = RefCell::new(10);
D. let x = new RefCell(10);
Solution
Step 1: Recall RefCell creation syntax
RefCell is created using the associated function new like RefCell::new(value).
Step 2: Check options
Only let x = RefCell::new(10); uses the correct syntax. Options A, B, and D are invalid Rust syntax for RefCell creation.
Final Answer:
let x = RefCell::new(10); -> Option C
Quick Check:
Use RefCell::new(value) to create [OK]
Hint: Use RefCell::new(value) to create a RefCell [OK]
Common Mistakes:
Using RefCell(10) without ::new
Trying to call RefCell::create which doesn't exist
Using new RefCell(10) like other languages
3. What will be the output of this Rust code?
use std::cell::RefCell;
fn main() {
let data = RefCell::new(5);
*data.borrow_mut() += 10;
println!("{}", data.borrow());
}
medium
A. 15
B. 5
C. Compilation error
D. Runtime panic
Solution
Step 1: Understand the code behavior
The RefCell holds 5 initially. The mutable borrow adds 10, changing the value to 15.
Step 2: Print the current value
The immutable borrow prints the updated value, which is 15.
Hint: borrow_mut lets you change the value inside RefCell [OK]
Common Mistakes:
Expecting original value 5 to print
Thinking borrow_mut causes compile error
Confusing borrow() and borrow_mut() usage
4. What error occurs when you try to borrow a RefCell mutably twice at the same time?
use std::cell::RefCell;
fn main() {
let cell = RefCell::new(10);
let mut1 = cell.borrow_mut();
let mut2 = cell.borrow_mut();
}
medium
A. Runtime panic due to multiple mutable borrows
B. Syntax error: borrow_mut() not found
C. No error, code runs fine
D. Compile-time borrow checker error
Solution
Step 1: Understand RefCell borrowing rules
RefCell enforces borrowing rules at runtime, so multiple mutable borrows cause a panic at runtime.
Step 2: Analyze the code
Two mutable borrows happen simultaneously, which is forbidden and triggers a runtime panic.
Final Answer:
Runtime panic due to multiple mutable borrows -> Option A
Quick Check:
RefCell panics on multiple mutable borrows [OK]
Hint: Only one mutable borrow allowed at runtime in RefCell [OK]
Common Mistakes:
Expecting compile-time error instead of runtime panic
Thinking multiple mutable borrows are allowed
Confusing syntax errors with borrowing errors
5. You want to safely mutate a value inside a struct shared only within one thread. Which is the best way to do this using RefCell?
struct Counter {
count: RefCell<i32>,
}
impl Counter {
fn new() -> Self {
Counter { count: RefCell::new(0) }
}
fn increment(&self) {
// Fill in this method
}
}
What code should replace the comment to increment the count safely?
hard
A. self.count = RefCell::new(*self.count.borrow() + 1);
B. *self.count.borrow_mut() += 1;
C. self.count.borrow() += 1;
D. self.count += 1;
Solution
Step 1: Understand how to mutate RefCell inside a method
To change the value inside RefCell, we borrow it mutably with borrow_mut() and then modify the dereferenced value.
Step 2: Check each option
*self.count.borrow_mut() += 1; correctly mutably borrows and increments. self.count = RefCell::new(*self.count.borrow() + 1); tries to replace the RefCell which is not allowed. self.count.borrow() += 1; tries to mutate an immutable borrow. self.count += 1; tries to add directly to RefCell which is invalid.
Final Answer:
*self.count.borrow_mut() += 1; -> Option B
Quick Check:
Use borrow_mut() to mutate RefCell value [OK]
Hint: Use *borrow_mut() to change RefCell's inner value [OK]
Common Mistakes:
Trying to assign a new RefCell instead of mutating inside
Using borrow() instead of borrow_mut() for mutation
Trying to add directly to RefCell without borrowing
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.