Module std::cell
[−]
[src]
Shareable mutable containers.
Values of the Cell<T>
`Celland
` and RefCell<T>
`RefCelltypes may be mutated through shared references (i.e. the common
` types may be mutated through shared references (i.e.
the common &T
`&Ttype), whereas most Rust types can only be mutated through unique (
` type), whereas most Rust types can only be mutated through unique (&mut T
`&mut T) references. We say that
`)
references. We say that Cell<T>
`Celland
` and RefCell<T>
`RefCell
Cell types come in two flavors: Cell<T>
`Celland
` and RefCell<T>
`RefCell.
`. Cell<T>
`Cellprovides
` provides get
`getand
` and set
`setmethods that change the interior value with a single method call.
`
methods that change the interior value with a single method call. Cell<T>
`Cellthough is only compatible with types that implement
` though is only
compatible with types that implement Copy
`Copy. For other types, one must use the
`. For other types, one must use the RefCell<T>
`RefCell
RefCell<T>
`RefCelluses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can claim temporary, exclusive, mutable access to the inner value. Borrows for
` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can
claim temporary, exclusive, mutable access to the inner value. Borrows for RefCell<T>
`RefCells are tracked 'at runtime', unlike Rust's native reference types which are entirely tracked statically, at compile time. Because
`s are
tracked 'at runtime', unlike Rust's native reference types which are entirely tracked
statically, at compile time. Because RefCell<T>
`RefCell
When to choose interior mutability
The more common inherited mutability, where one must have unique access to mutate a value, is one of the key language elements that enables Rust to reason strongly about pointer aliasing, statically preventing crash bugs. Because of that, inherited mutability is preferred, and interior mutability is something of a last resort. Since cell types enable mutation where it would otherwise be disallowed though, there are occasions when interior mutability might be appropriate, or even must be used, e.g.
- Introducing inherited mutability roots to shared types.
- Implementation details of logically-immutable methods.
- Mutating implementations of
clone
`clone`.
Introducing inherited mutability roots to shared types
Shared smart pointer types, including Rc<T>
`Rcand
` and Arc<T>
`Arc
It's very common then to put a RefCell<T>
`RefCell
use std::collections::HashMap; use std::cell::RefCell; use std::rc::Rc; fn main() { let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new())); shared_map.borrow_mut().insert("africa", 92388); shared_map.borrow_mut().insert("kyoto", 11837); shared_map.borrow_mut().insert("piccadilly", 11826); shared_map.borrow_mut().insert("marbles", 38); }
Note that this example uses Rc<T>
`Rcand not
` and not Arc<T>
`Arc.
`. RefCell<T>
`RefCells are for single-threaded scenarios. Consider using
`s are for single-threaded
scenarios. Consider using Mutex<T>
`Mutex
Implementation details of logically-immutable methods
Occasionally it may be desirable not to expose in an API that there is mutation happening
"under the hood". This may be because logically the operation is immutable, but e.g. caching
forces the implementation to perform mutation; or because you must employ mutation to implement
a trait method that was originally defined to take &self
`&self`.
use std::cell::RefCell; struct Graph { edges: Vec<(i32, i32)>, span_tree_cache: RefCell<Option<Vec<(i32, i32)>>> } impl Graph { fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> { // Create a new scope to contain the lifetime of the // dynamic borrow { // Take a reference to the inside of cache cell let mut cache = self.span_tree_cache.borrow_mut(); if cache.is_some() { return cache.as_ref().unwrap().clone(); } let span_tree = self.calc_span_tree(); *cache = Some(span_tree); } // Recursive call to return the just-cached value. // Note that if we had not let the previous borrow // of the cache fall out of scope then the subsequent // recursive borrow would cause a dynamic thread panic. // This is the major hazard of using `RefCell`. self.minimum_spanning_tree() } }
Mutating implementations of clone
`clone`
This is simply a special - but common - case of the previous: hiding mutability for operations
that appear to be immutable. The clone
`clonemethod is expected to not change the source value, and is declared to take
` method is expected to not change the source value, and
is declared to take &self
`&self, not
`, not &mut self
`&mut self. Therefore any mutation that happens in the
`. Therefore any mutation that happens in the
clone
`clonemethod must use cell types. For example,
` method must use cell types. For example, Rc<T>
`Rcmaintains its reference counts within a
` maintains its reference counts within a
Cell<T>
`Cell
use std::cell::Cell; struct Rc<T> { ptr: *mut RcBox<T> } struct RcBox<T> { value: T, refcount: Cell<usize> } impl<T> Clone for Rc<T> { fn clone(&self) -> Rc<T> { unsafe { (*self.ptr).refcount.set((*self.ptr).refcount.get() + 1); Rc { ptr: self.ptr } } } }
Structs
Cell |
A mutable memory location that admits only |
Ref |
Wraps a borrowed reference to a value in a |
RefCell |
A mutable memory location with dynamically checked borrow rules |
RefMut |
A wrapper type for a mutably borrowed value from a |
UnsafeCell |
The core primitive for interior mutability in Rust. |
Enums
BorrowState |
[Unstable] An enumeration of values returned from the |
Functions
clone_ref |
[Unstable] Copies a |