Struct OnceCell

pub struct OnceCell<T> { pub(in ::cell::once) inner: UnsafeCell<Option<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());

Fields

inner: UnsafeCell<Option<T>>

Implementations

impl<T> OnceCell<T>

const fn new() -> OnceCell<T>

Creates a new uninitialized cell.

const fn new_init(init_value: T) -> OnceCell<T>

Creates a new initialized cell.

This is equivalent to OnceCell::from(value), but can be used in const contexts, unlike the From implementation.

Examples

#![feature(once_cell_new_init)]
use std::cell::OnceCell;

const CELL: OnceCell<i32> = OnceCell::new_init(1);
assert_eq!(CELL.get(), Some(&1));

let cell = OnceCell::new_init(String::from("kitty"));
assert_eq!(cell.set(String::from("puppy")), Err(String::from("puppy")));
assert_eq!(cell.get(), Some(&"kitty".to_string()));
fn get(&self) -> Option<&T>

Gets the reference to the underlying value.

Returns None if the cell is uninitialized.

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

Gets the mutable reference to the underlying value.

Returns None if the cell is uninitialized.

fn set(&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, 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, 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>(&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, 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>(&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))
fn try_init<F, E>(&self, f: F) -> Result<&T, E>
where
    F: FnOnce() -> Result<T, E>,
const fn into_inner(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(&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);

Trait Implementations

impl<T> !Sync for OnceCell<T>

impl<T> Default for OnceCell<T>

fn default() -> Self

impl<T> From<T> for OnceCell<T>

fn from(value: T) -> Self

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

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

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

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

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

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

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

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

Auto Trait Implementations

impl<T> !Freeze for OnceCell<T>

impl<T> !RefUnwindSafe for OnceCell<T>

impl<T> Send for OnceCell<T> where UnsafeCell<Option<T>>: Send,

impl<T> Unpin for OnceCell<T> where UnsafeCell<Option<T>>: Unpin,

impl<T> UnsafeUnpin for OnceCell<T> where UnsafeCell<Option<T>>: UnsafeUnpin,

impl<T> UnwindSafe for OnceCell<T> where UnsafeCell<Option<T>>: UnwindSafe,

Blanket Implementations

impl<T> Any for OnceCell<T> where T: 'static + ?Sized,

fn type_id(&self) -> TypeId

impl<T> Borrow<T> for OnceCell<T> where T: ?Sized,

fn borrow(&self) -> &T

impl<T> BorrowMut<T> for OnceCell<T> where T: ?Sized,

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

impl<T> CloneToUninit for OnceCell<T> where T: Clone,

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

impl<T> From<T> for OnceCell<T>

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> From<never> for OnceCell<T>

fn from(t: never) -> T

impl<T> SizeHint for OnceCell<T> where T: ?Sized,

fn lower_bound(&self) -> usize
fn upper_bound(&self) -> Option<usize>

impl<T> SizedTypeProperties for OnceCell<T>

impl<T, U> Into<U> for OnceCell<T> where U: From<T>,

fn into(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<U> for OnceCell<T> where U: Into<T>,

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

impl<T, U> TryInto<U> for OnceCell<T> where U: TryFrom<T>,

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