1.5 KiB
date | id | title |
---|---|---|
20200929 | 16e7cc98-b9fb-40c3-b2cf-41d3035275be | RefCell<T> |
Introduction
Interior mutability is a design pattern in Rust that allows you to
mutate data even when there are immutable references to that data;
normally, this action is disallowed by the borrowing rules. To mutate
data, the pattern uses unsafe
code inside a data structure to bend
Rust’s usual rules that govern mutation and borrowing. We can use types
that use the interior mutability pattern when we can ensure that the
borrowing rules will be followed at runtime, even though the compiler
can’t guarantee that. The unsafe
code involved is then wrapped in a
safe API, and the outer type is still immutable.
Reason to choose RefCell<T>
Because RefCell<T>
allows mutable borrows checked at runtime, you can
mutate the value inside the RefCell<T>
even when the RefCell<T>
is
immutable.
Example
This won't compile:
fn main() {
let x = 5;
let y = &mut x;
}
This will:
#[derive(Debug)]
enum List {
Cons(Rc<RefCell<i32>>, Rc<List>),
Nil,
}
use crate::List::{Cons, Nil};
use std::cell::RefCell;
use std::rc::Rc;
fn main() {
let value = Rc::new(RefCell::new(5));
let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));
let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));
let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a));
*value.borrow_mut() += 10;
println!("a after = {:?}", a);
println!("b after = {:?}", b);
println!("c after = {:?}", c);
}