use crate::cell::UnsafeCell; use crate::{fmt, mem}; /// 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`]. /// /// [`RefCell`]: crate::cell::RefCell /// [`Cell`]: crate::cell::Cell /// [`std::sync::OnceLock`]: ../../std/sync/struct.OnceLock.html /// /// # 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()); /// ``` #[stable(feature = "once_cell", since = "1.70.0")] pub struct OnceCell { // Invariant: written to at most once. inner: UnsafeCell>, } impl OnceCell { /// Creates a new uninitialized cell. #[inline] #[must_use] #[stable(feature = "once_cell", since = "1.70.0")] #[rustc_const_stable(feature = "once_cell", since = "1.70.0")] pub const fn new() -> OnceCell { OnceCell { inner: UnsafeCell::new(None) } } /// Gets the reference to the underlying value. /// /// Returns `None` if the cell is uninitialized. #[inline] #[stable(feature = "once_cell", since = "1.70.0")] pub fn get(&self) -> Option<&T> { // SAFETY: Safe due to `inner`'s invariant unsafe { &*self.inner.get() }.as_ref() } /// Gets the mutable reference to the underlying value. /// /// Returns `None` if the cell is uninitialized. #[inline] #[stable(feature = "once_cell", since = "1.70.0")] pub fn get_mut(&mut self) -> Option<&mut T> { self.inner.get_mut().as_mut() } /// 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()); /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] pub fn set(&self, value: T) -> Result<(), T> { match self.try_insert(value) { Ok(_) => Ok(()), Err((_, value)) => Err(value), } } /// 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((¤t_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()); /// ``` #[inline] #[unstable(feature = "once_cell_try_insert", issue = "116693")] pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { if let Some(old) = self.get() { return Err((old, value)); } // SAFETY: This is the only place where we set the slot, no races // due to reentrancy/concurrency are possible, and we've // checked that slot is currently `None`, so this write // maintains the `inner`'s invariant. let slot = unsafe { &mut *self.inner.get() }; Ok(slot.insert(value)) } /// 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); /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, { match self.get_or_try_init(|| Ok::(f())) { Ok(val) => val, } } /// 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); /// ``` #[inline] #[unstable(feature = "once_cell_get_mut", issue = "121641")] pub fn get_mut_or_init(&mut self, f: F) -> &mut T where F: FnOnce() -> T, { match self.get_mut_or_try_init(|| Ok::(f())) { Ok(val) => val, } } /// 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 { /// Ok(92) /// }); /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` #[unstable(feature = "once_cell_try", issue = "109737")] pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { if let Some(val) = self.get() { return Ok(val); } self.try_init(f) } /// 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 = 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)) /// ``` #[unstable(feature = "once_cell_get_mut", issue = "121641")] pub fn get_mut_or_try_init(&mut self, f: F) -> Result<&mut T, E> where F: FnOnce() -> Result, { if self.get().is_none() { self.try_init(f)?; } Ok(self.get_mut().unwrap()) } // Avoid inlining the initialization closure into the common path that fetches // the already initialized value #[cold] fn try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, { let val = f()?; // Note that *some* forms of reentrant initialization might lead to // UB (see `reentrant_init` test). I believe that just removing this // `panic`, while keeping `try_insert` would be sound, but it seems // better to panic, rather than to silently use an old value. if let Ok(val) = self.try_insert(val) { Ok(val) } else { panic!("reentrant init") } } /// Consumes the cell, returning the wrapped value. /// /// Returns `None` if the cell was uninitialized. /// /// # Examples /// /// ``` /// use std::cell::OnceCell; /// /// let cell: OnceCell = 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())); /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] #[rustc_const_stable(feature = "const_cell_into_inner", since = "1.83.0")] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn into_inner(self) -> Option { // Because `into_inner` takes `self` by value, the compiler statically verifies // that it is not currently borrowed. So it is safe to move out `Option`. self.inner.into_inner() } /// 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 = 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); /// ``` #[inline] #[stable(feature = "once_cell", since = "1.70.0")] pub fn take(&mut self) -> Option { mem::take(self).into_inner() } } #[stable(feature = "once_cell", since = "1.70.0")] impl Default for OnceCell { #[inline] fn default() -> Self { Self::new() } } #[stable(feature = "once_cell", since = "1.70.0")] impl fmt::Debug for OnceCell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut d = f.debug_tuple("OnceCell"); match self.get() { Some(v) => d.field(v), None => d.field(&format_args!("")), }; d.finish() } } #[stable(feature = "once_cell", since = "1.70.0")] impl Clone for OnceCell { #[inline] fn clone(&self) -> OnceCell { let res = OnceCell::new(); if let Some(value) = self.get() { match res.set(value.clone()) { Ok(()) => (), Err(_) => unreachable!(), } } res } } #[stable(feature = "once_cell", since = "1.70.0")] impl PartialEq for OnceCell { #[inline] fn eq(&self, other: &Self) -> bool { self.get() == other.get() } } #[stable(feature = "once_cell", since = "1.70.0")] impl Eq for OnceCell {} #[stable(feature = "once_cell", since = "1.70.0")] impl From for OnceCell { /// Creates a new `OnceCell` which already contains the given `value`. #[inline] fn from(value: T) -> Self { OnceCell { inner: UnsafeCell::new(Some(value)) } } } // Just like for `Cell` this isn't needed, but results in nicer error messages. #[stable(feature = "once_cell", since = "1.70.0")] impl !Sync for OnceCell {}