Leverage &mut in OnceLock when possible

Signed-off-by: tison <wander4096@gmail.com>
This commit is contained in:
tison
2025-11-30 10:42:41 +08:00
parent 3ff30e7eaf
commit 0e336684fd
+27 -18
View File
@@ -1,3 +1,4 @@
use super::once::OnceExclusiveState;
use crate::cell::UnsafeCell;
use crate::fmt;
use crate::marker::PhantomData;
@@ -152,8 +153,8 @@ pub const fn new() -> OnceLock<T> {
#[stable(feature = "once_cell", since = "1.70.0")]
#[rustc_should_not_be_called_on_const_items]
pub fn get(&self) -> Option<&T> {
if self.is_initialized() {
// Safe b/c checked is_initialized
if self.initialized() {
// Safe b/c checked initialized
Some(unsafe { self.get_unchecked() })
} else {
None
@@ -170,8 +171,8 @@ pub fn get(&self) -> Option<&T> {
#[inline]
#[stable(feature = "once_cell", since = "1.70.0")]
pub fn get_mut(&mut self) -> Option<&mut T> {
if self.is_initialized() {
// Safe b/c checked is_initialized and we have a unique access
if self.initialized_mut() {
// Safe b/c checked initialized and we have a unique access
Some(unsafe { self.get_unchecked_mut() })
} else {
None
@@ -402,14 +403,12 @@ pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
// NOTE: We need to perform an acquire on the state in this method
// in order to correctly synchronize `LazyLock::force`. This is
// currently done by calling `self.get()`, which in turn calls
// `self.is_initialized()`, which in turn performs the acquire.
// `self.initialized()`, which in turn performs the acquire.
if let Some(value) = self.get() {
return Ok(value);
}
self.initialize(f)?;
debug_assert!(self.is_initialized());
// SAFETY: The inner value has been initialized
Ok(unsafe { self.get_unchecked() })
}
@@ -451,10 +450,10 @@ pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
where
F: FnOnce() -> Result<T, E>,
{
if self.get().is_none() {
if self.get_mut().is_none() {
self.initialize(f)?;
}
debug_assert!(self.is_initialized());
// SAFETY: The inner value has been initialized
Ok(unsafe { self.get_unchecked_mut() })
}
@@ -503,22 +502,32 @@ pub fn into_inner(mut self) -> Option<T> {
#[inline]
#[stable(feature = "once_cell", since = "1.70.0")]
pub fn take(&mut self) -> Option<T> {
if self.is_initialized() {
if self.initialized_mut() {
self.once = Once::new();
// SAFETY: `self.value` is initialized and contains a valid `T`.
// `self.once` is reset, so `is_initialized()` will be false again
// `self.once` is reset, so `initialized()` will be false again
// which prevents the value from being read twice.
unsafe { Some((&mut *self.value.get()).assume_init_read()) }
unsafe { Some(self.value.get_mut().assume_init_read()) }
} else {
None
}
}
#[inline]
fn is_initialized(&self) -> bool {
fn initialized(&self) -> bool {
self.once.is_completed()
}
#[inline]
fn initialized_mut(&mut self) -> bool {
// `state()` does not perform an atomic load, so prefer it over `is_complete()`.
let state = self.once.state();
match state {
OnceExclusiveState::Complete => true,
_ => false,
}
}
#[cold]
#[optimize(size)]
fn initialize<F, E>(&self, f: F) -> Result<(), E>
@@ -552,7 +561,7 @@ fn initialize<F, E>(&self, f: F) -> Result<(), E>
/// The cell must be initialized
#[inline]
unsafe fn get_unchecked(&self) -> &T {
debug_assert!(self.is_initialized());
debug_assert!(self.initialized());
unsafe { (&*self.value.get()).assume_init_ref() }
}
@@ -561,8 +570,8 @@ unsafe fn get_unchecked(&self) -> &T {
/// The cell must be initialized
#[inline]
unsafe fn get_unchecked_mut(&mut self) -> &mut T {
debug_assert!(self.is_initialized());
unsafe { (&mut *self.value.get()).assume_init_mut() }
debug_assert!(self.initialized_mut());
unsafe { self.value.get_mut().assume_init_mut() }
}
}
@@ -689,11 +698,11 @@ impl<T: Eq> Eq for OnceLock<T> {}
unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
#[inline]
fn drop(&mut self) {
if self.is_initialized() {
if self.initialized_mut() {
// SAFETY: The cell is initialized and being dropped, so it can't
// be accessed again. We also don't touch the `T` other than
// dropping it, which validates our usage of #[may_dangle].
unsafe { (&mut *self.value.get()).assume_init_drop() };
unsafe { self.value.get_mut().assume_init_drop() };
}
}
}