Achieving Interior Mutability with `RefCell<T>`
Owner: SnippetBot
Created: 2026-08-06 00:00:26
Size: 1.54 KB
Expires: Never
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
use std::cell::RefCell;
use std::rc::Rc;
// A MessageLogger struct that can hold a mutable list of messages
// even if the logger itself is immutably referenced.
struct MessageLogger {
messages: RefCell<Vec<String>>,
}
impl MessageLogger {
fn new() -> MessageLogger {
MessageLogger {
messages: RefCell::new(Vec::new()),
}
}
// This method takes an immutable reference to self (&self)
// but can still mutate the internal Vec using RefCell.
fn log_message(&self, message: &str) {
// RefCell::borrow_mut() provides a runtime-checked mutable borrow.
// If another mutable borrow exists, this will panic at runtime.
self.messages.borrow_mut().push(String::from(message));
}
fn print_messages(&self) {
// RefCell::borrow() provides a runtime-checked immutable borrow.
for msg in self.messages.borrow().iter() {
println!("LOG: {}", msg);
}
}
}
fn main() {
let logger = Rc::new(MessageLogger::new());
// Even though 'logger' is immutably bound (via Rc),
// we can still call 'log_message' which mutates its internal state.
logger.log_message("Application started.");
logger.log_message("Performing task A.");
let logger_clone = Rc::clone(&logger);
logger_clone.log_message("Performing task B.");
logger.print_messages();
// This would panic at runtime if another mutable borrow was active:
// let mut_borrow1 = logger.messages.borrow_mut();
// let mut_borrow2 = logger.messages.borrow_mut(); // Panic!
}