# Module std::cell 1.0.0 [−] [src]

Shareable mutable containers.

Values of the `Cell<T>` and `RefCell<T>` types may be mutated through shared references (i.e. the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`) references. We say that `Cell<T>` and `RefCell<T>` provide 'interior mutability', in contrast with typical Rust types that exhibit 'inherited mutability'.

Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` provides `get` and `set` methods that change the interior value with a single method call. `Cell<T>` though is only compatible with types that implement `Copy`. For other types, one must use the `RefCell<T>` type, acquiring a write lock before mutating.

`RefCell<T>` 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>`s are tracked 'at runtime', unlike Rust's native reference types which are entirely tracked statically, at compile time. Because `RefCell<T>` borrows are dynamic it is possible to attempt to borrow a value that is already mutably borrowed; when this happens it results in thread panic.

# 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 mutability 'inside' of something immutable
- Implementation details of logically-immutable methods.
- Mutating implementations of `Clone`.

## Introducing mutability 'inside' of something immutable

Many shared smart pointer types, including `Rc<T>` and `Arc<T>`, provide containers that can be cloned and shared between multiple parties. Because the contained values may be multiply-aliased, they can only be borrowed with `&`, not `&mut`. Without cells it would be impossible to mutate data inside of these smart pointers at all.

It's very common then to put a `RefCell<T>` inside shared pointer types to reintroduce mutability:

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); }

    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>` and not `Arc<T>`. `RefCell<T>`s are for single-threaded scenarios. Consider using `RwLock<T>` or `Mutex<T>` if you need shared mutability in a multi-threaded situation.

## 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`.

fn main() { #![allow(dead_code)] 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() } fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] } } }

    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`

This is simply a special - but common - case of the previous: hiding mutability for operations that appear to be immutable. The `clone` method is expected to not change the source value, and is declared to take `&self`, not `&mut self`. Therefore any mutation that happens in the `clone` method must use cell types. For example, `Rc<T>` maintains its reference counts within a `Cell<T>`.

fn main() { use std::cell::Cell; struct Rc<T> { ptr: *mut RcBox<T> } struct RcBox<T> { #[allow(dead_code)] 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 } } } } }

    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 `Copy` data.
Ref | Wraps a borrowed reference to a value in a `RefCell` box. A wrapper type for an immutably borrowed value from a `RefCell<T>`.
RefCell | A mutable memory location with dynamically checked borrow rules
RefMut | A wrapper type for a mutably borrowed value from a `RefCell<T>`.
UnsafeCell | The core primitive for interior mutability in Rust.

## Enums

BorrowState | [Unstable] An enumeration of values returned from the `state` method on a `RefCell<T>`.

# Help

## Keyboard Shortcuts

?
  Show this help dialog
S
  Focus the search field
⇤
  Move up in search results
⇥
  Move down in search results
⏎
  Go to active search result
+
  Collapse/expand all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g. `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g. `vec -> usize` or `* -> vec`)