Struct OnceCell

struct OnceCell<T> { ... }

A cell which can nominally be written to only once.

This allows obtaining a shared &T reference to its inner value without copying or replacing it (unlike Cell), and without runtime borrow checks (unlike RefCell). However, only immutable references can be obtained unless one has a mutable reference to the cell itself. In the same vein, the cell can only be re-initialized with such a mutable reference.

A OnceCell can be thought of as a safe abstraction over uninitialized data that becomes initialized once written.

For a thread-safe version of this struct, see std::sync::OnceLock.

Examples

use std::cell::OnceCell;

let cell = OnceCell::new();
assert!(cell.get().is_none());

let value: &String = cell.get_or_init(|| {
    "Hello, World!".to_string()
});
assert_eq!(value, "Hello, World!");
assert!(cell.get().is_some());

Implementations

impl<T> OnceCell<T>

const fn new() -> OnceCell<T>

Creates a new uninitialized cell.

fn get(self: &Self) -> Option<&T>

Gets the reference to the underlying value.

Returns None if the cell is uninitialized.

fn get_mut(self: &mut Self) -> Option<&mut T>

Gets the mutable reference to the underlying value.

Returns None if the cell is uninitialized.

fn set(self: &Self, value: T) -> Result<(), T>

Initializes the contents of the cell to value.

Errors

This method returns Ok(()) if the cell was uninitialized and Err(value) if it was already initialized.

Examples

use std::cell::OnceCell;

let cell = OnceCell::new();
assert!(cell.get().is_none());

assert_eq!(cell.set(92), Ok(()));
assert_eq!(cell.set(62), Err(62));

assert!(cell.get().is_some());
fn try_insert(self: &Self, value: T) -> Result<&T, (&T, T)>

Initializes the contents of the cell to value if the cell was uninitialized, then returns a reference to it.

Errors

This method returns Ok(&value) if the cell was uninitialized and Err((&current_value, value)) if it was already initialized.

Examples

#![feature(once_cell_try_insert)]

use std::cell::OnceCell;

let cell = OnceCell::new();
assert!(cell.get().is_none());

assert_eq!(cell.try_insert(92), Ok(&92));
assert_eq!(cell.try_insert(62), Err((&92, 62)));

assert!(cell.get().is_some());
fn get_or_init<F>(self: &Self, f: F) -> &T
where
    F: FnOnce() -> T

Gets the contents of the cell, initializing it to f() if the cell was uninitialized.

Panics

If f() panics, the panic is propagated to the caller, and the cell remains uninitialized.

It is an error to reentrantly initialize the cell from f. Doing so results in a panic.

Examples

use std::cell::OnceCell;

let cell = OnceCell::new();
let value = cell.get_or_init(|| 92);
assert_eq!(value, &92);
let value = cell.get_or_init(|| unreachable!());
assert_eq!(value, &92);
fn get_mut_or_init<F>(self: &mut Self, f: F) -> &mut T
where
    F: FnOnce() -> T

Gets the mutable reference of the contents of the cell, initializing it to f() if the cell was uninitialized.

Panics

If f() panics, the panic is propagated to the caller, and the cell remains uninitialized.

Examples

#![feature(once_cell_get_mut)]

use std::cell::OnceCell;

let mut cell = OnceCell::new();
let value = cell.get_mut_or_init(|| 92);
assert_eq!(*value, 92);

*value += 2;
assert_eq!(*value, 94);

let value = cell.get_mut_or_init(|| unreachable!());
assert_eq!(*value, 94);
fn get_or_try_init<F, E>(self: &Self, f: F) -> Result<&T, E>
where
    F: FnOnce() -> Result<T, E>

Gets the contents of the cell, initializing it to f() if the cell was uninitialized. If the cell was uninitialized and f() failed, an error is returned.

Panics

If f() panics, the panic is propagated to the caller, and the cell remains uninitialized.

It is an error to reentrantly initialize the cell from f. Doing so results in a panic.

Examples

#![feature(once_cell_try)]

use std::cell::OnceCell;

let cell = OnceCell::new();
assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
assert!(cell.get().is_none());
let value = cell.get_or_try_init(|| -> Result<i32, ()> {
    Ok(92)
});
assert_eq!(value, Ok(&92));
assert_eq!(cell.get(), Some(&92))
fn get_mut_or_try_init<F, E>(self: &mut Self, f: F) -> Result<&mut T, E>
where
    F: FnOnce() -> Result<T, E>

Gets the mutable reference of the contents of the cell, initializing it to f() if the cell was uninitialized. If the cell was uninitialized and f() failed, an error is returned.

Panics

If f() panics, the panic is propagated to the caller, and the cell remains uninitialized.

Examples

#![feature(once_cell_get_mut)]

use std::cell::OnceCell;

let mut cell: OnceCell<u32> = OnceCell::new();

// Failed attempts to initialize the cell do not change its contents
assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err());
assert!(cell.get().is_none());

let value = cell.get_mut_or_try_init(|| "1234".parse());
assert_eq!(value, Ok(&mut 1234));

let Ok(value) = value else { return; };
*value += 2;
assert_eq!(cell.get(), Some(&1236))
const fn into_inner(self: Self) -> Option<T>

Consumes the cell, returning the wrapped value.

Returns None if the cell was uninitialized.

Examples

use std::cell::OnceCell;

let cell: OnceCell<String> = OnceCell::new();
assert_eq!(cell.into_inner(), None);

let cell = OnceCell::new();
let _ = cell.set("hello".to_owned());
assert_eq!(cell.into_inner(), Some("hello".to_owned()));
fn take(self: &mut Self) -> Option<T>

Takes the value out of this OnceCell, moving it back to an uninitialized state.

Has no effect and returns None if the OnceCell is uninitialized.

Safety is guaranteed by requiring a mutable reference.

Examples

use std::cell::OnceCell;

let mut cell: OnceCell<String> = OnceCell::new();
assert_eq!(cell.take(), None);

let mut cell = OnceCell::new();
let _ = cell.set("hello".to_owned());
assert_eq!(cell.take(), Some("hello".to_owned()));
assert_eq!(cell.get(), None);

impl<T> Any for OnceCell<T>

fn type_id(self: &Self) -> TypeId

impl<T> Borrow for OnceCell<T>

fn borrow(self: &Self) -> &T

impl<T> BorrowMut for OnceCell<T>

fn borrow_mut(self: &mut Self) -> &mut T

impl<T> CloneToUninit for OnceCell<T>

unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)

impl<T> Default for OnceCell<T>

fn default() -> Self

impl<T> Freeze for OnceCell<T>

impl<T> From for OnceCell<T>

fn from(value: T) -> Self

Creates a new OnceCell<T> which already contains the given value.

impl<T> From for OnceCell<T>

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> From for OnceCell<T>

fn from(t: never) -> T

impl<T> RefUnwindSafe for OnceCell<T>

impl<T> Send for OnceCell<T>

impl<T> Sync for OnceCell<T>

impl<T> Unpin for OnceCell<T>

impl<T> UnsafeUnpin for OnceCell<T>

impl<T> UnwindSafe for OnceCell<T>

impl<T, U> Into for OnceCell<T>

fn into(self: Self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom for OnceCell<T>

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

impl<T, U> TryInto for OnceCell<T>

fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>

impl<T: Clone> Clone for OnceCell<T>

fn clone(self: &Self) -> OnceCell<T>

impl<T: Eq> Eq for OnceCell<T>

impl<T: PartialEq> PartialEq for OnceCell<T>

fn eq(self: &Self, other: &Self) -> bool

impl<T: fmt::Debug> Debug for OnceCell<T>

fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result