RefCell lets you change data even when Rust normally would not allow it. It helps manage data safely inside a single thread.
RefCell overview in Rust
use std::cell::RefCell; let data = RefCell::new(5); // Borrow immutably let value = data.borrow(); // Borrow mutably let mut value_mut = data.borrow_mut();
RefCell::new(value) creates a new RefCell holding the value.
borrow() gives an immutable reference, borrow_mut() gives a mutable reference.
use std::cell::RefCell; let data = RefCell::new(10); let val = data.borrow(); println!("Value: {}", *val);
use std::cell::RefCell; let data = RefCell::new(10); { let mut val_mut = data.borrow_mut(); *val_mut += 5; } println!("Updated value: {}", *data.borrow());
use std::cell::RefCell; let data = RefCell::new(vec![1, 2, 3]); data.borrow_mut().push(4); println!("Vector: {:?}", *data.borrow());
This program shows how RefCell allows changing a value safely inside one thread. It borrows the value immutably, then mutably changes it, then reads it again.
use std::cell::RefCell;
fn main() {
let shared_number = RefCell::new(100);
// Borrow immutably
let num1 = shared_number.borrow();
println!("First borrow: {}", *num1);
// Borrow mutably
{
let mut num2 = shared_number.borrow_mut();
*num2 += 50;
println!("After mutation: {}", *num2);
}
// Borrow immutably again
let num3 = shared_number.borrow();
println!("Final value: {}", *num3);
}RefCell checks borrowing rules at runtime, so borrowing errors cause the program to panic.
Use RefCell only when you are sure you need interior mutability inside one thread.
For multi-threaded cases, use types like Mutex or RwLock.
RefCell allows changing data even when Rust normally forbids it.
It enforces borrowing rules at runtime, not compile time.
Use it for safe interior mutability inside a single thread.
Practice
RefCell in Rust?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 DQuick Check:
RefCell enables interior mutability = B [OK]
- Confusing RefCell with thread-safe types
- Thinking RefCell enforces compile-time checks
- Assuming RefCell replaces Box for heap allocation
RefCell containing an integer value 10?Solution
Step 1: Recall RefCell creation syntax
RefCell is created using the associated functionnewlikeRefCell::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 CQuick Check:
Use RefCell::new(value) to create [OK]
- Using RefCell(10) without ::new
- Trying to call RefCell::create which doesn't exist
- Using new RefCell(10) like other languages
use std::cell::RefCell;
fn main() {
let data = RefCell::new(5);
*data.borrow_mut() += 10;
println!("{}", data.borrow());
}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.Final Answer:
15 -> Option AQuick Check:
RefCell allows mutation inside borrow_mut = 15 [OK]
- Expecting original value 5 to print
- Thinking borrow_mut causes compile error
- Confusing borrow() and borrow_mut() usage
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();
}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 AQuick Check:
RefCell panics on multiple mutable borrows [OK]
- Expecting compile-time error instead of runtime panic
- Thinking multiple mutable borrows are allowed
- Confusing syntax errors with borrowing errors
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?Solution
Step 1: Understand how to mutate RefCell inside a method
To change the value inside RefCell, we borrow it mutably withborrow_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 BQuick Check:
Use borrow_mut() to mutate RefCell value [OK]
- 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
Ready to prove it?
Pass the test and this pattern moves unknown
