Skip to main content

std/sync/
once_lock.rs

1use super::once::OnceExclusiveState;
2use crate::cell::UnsafeCell;
3use crate::fmt;
4use crate::marker::PhantomData;
5use crate::mem::MaybeUninit;
6use crate::panic::{RefUnwindSafe, UnwindSafe};
7use crate::sync::Once;
8
9/// A synchronization primitive which can nominally be written to only once.
10///
11/// This type is a thread-safe [`OnceCell`], and can be used in statics.
12/// In many simple cases, you can use [`LazyLock<T, F>`] instead to get the benefits of this type
13/// with less effort: `LazyLock<T, F>` "looks like" `&T` because it initializes with `F` on deref!
14/// Where OnceLock shines is when LazyLock is too simple to support a given case, as LazyLock
15/// doesn't allow additional inputs to its function after you call [`LazyLock::new(|| ...)`].
16///
17/// A `OnceLock` can be thought of as a safe abstraction over uninitialized data that becomes
18/// initialized once written.
19///
20/// Unlike [`Mutex`](crate::sync::Mutex), `OnceLock` is never poisoned on panic.
21///
22/// [`OnceCell`]: crate::cell::OnceCell
23/// [`LazyLock<T, F>`]: crate::sync::LazyLock
24/// [`LazyLock::new(|| ...)`]: crate::sync::LazyLock::new
25///
26/// # Examples
27///
28/// Writing to a `OnceLock` from a separate thread:
29///
30/// ```
31/// use std::sync::OnceLock;
32///
33/// static CELL: OnceLock<usize> = OnceLock::new();
34///
35/// // `OnceLock` has not been written to yet.
36/// assert!(CELL.get().is_none());
37///
38/// // Spawn a thread and write to `OnceLock`.
39/// std::thread::spawn(|| {
40///     let value = CELL.get_or_init(|| 12345);
41///     assert_eq!(value, &12345);
42/// })
43/// .join()
44/// .unwrap();
45///
46/// // `OnceLock` now contains the value.
47/// assert_eq!(
48///     CELL.get(),
49///     Some(&12345),
50/// );
51/// ```
52///
53/// You can use `OnceLock` to implement a type that requires "append-only" logic:
54///
55/// ```
56/// use std::sync::{OnceLock, atomic::{AtomicU32, Ordering}};
57/// use std::thread;
58///
59/// struct OnceList<T> {
60///     data: OnceLock<T>,
61///     next: OnceLock<Box<OnceList<T>>>,
62/// }
63/// impl<T> OnceList<T> {
64///     const fn new() -> OnceList<T> {
65///         OnceList { data: OnceLock::new(), next: OnceLock::new() }
66///     }
67///     fn push(&self, value: T) {
68///         // FIXME: this impl is concise, but is also slow for long lists or many threads.
69///         // as an exercise, consider how you might improve on it while preserving the behavior
70///         if let Err(value) = self.data.set(value) {
71///             let next = self.next.get_or_init(|| Box::new(OnceList::new()));
72///             next.push(value)
73///         };
74///     }
75///     fn contains(&self, example: &T) -> bool
76///     where
77///         T: PartialEq,
78///     {
79///         self.data.get().map(|item| item == example).filter(|v| *v).unwrap_or_else(|| {
80///             self.next.get().map(|next| next.contains(example)).unwrap_or(false)
81///         })
82///     }
83/// }
84///
85/// // Let's exercise this new Sync append-only list by doing a little counting
86/// static LIST: OnceList<u32> = OnceList::new();
87/// static COUNTER: AtomicU32 = AtomicU32::new(0);
88///
89/// # const LEN: u32 = if cfg!(miri) { 50 } else { 1000 };
90/// # /*
91/// const LEN: u32 = 1000;
92/// # */
93/// thread::scope(|s| {
94///     for _ in 0..thread::available_parallelism().unwrap().get() {
95///         s.spawn(|| {
96///             while let i @ 0..LEN = COUNTER.fetch_add(1, Ordering::Relaxed) {
97///                 LIST.push(i);
98///             }
99///         });
100///     }
101/// });
102///
103/// for i in 0..LEN {
104///     assert!(LIST.contains(&i));
105/// }
106///
107/// ```
108#[stable(feature = "once_cell", since = "1.70.0")]
109pub struct OnceLock<T> {
110    // FIXME(nonpoison_once): switch to nonpoison version once it is available
111    once: Once,
112    // Whether or not the value is initialized is tracked by `once.is_completed()`.
113    value: UnsafeCell<MaybeUninit<T>>,
114    /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
115    ///
116    /// ```compile_fail,E0597
117    /// use std::sync::OnceLock;
118    ///
119    /// struct A<'a>(&'a str);
120    ///
121    /// impl<'a> Drop for A<'a> {
122    ///     fn drop(&mut self) {}
123    /// }
124    ///
125    /// let cell = OnceLock::new();
126    /// {
127    ///     let s = String::new();
128    ///     let _ = cell.set(A(&s));
129    /// }
130    /// ```
131    _marker: PhantomData<T>,
132}
133
134impl<T> OnceLock<T> {
135    /// Creates a new uninitialized cell.
136    #[inline]
137    #[must_use]
138    #[stable(feature = "once_cell", since = "1.70.0")]
139    #[rustc_const_stable(feature = "once_cell", since = "1.70.0")]
140    pub const fn new() -> OnceLock<T> {
141        OnceLock {
142            once: Once::new(),
143            value: UnsafeCell::new(MaybeUninit::uninit()),
144            _marker: PhantomData,
145        }
146    }
147
148    /// Creates a new initialized cell.
149    ///
150    /// This is equivalent to `OnceLock::from(value)`, but can be used in
151    /// const contexts, unlike the `From` implementation.
152    ///
153    /// # Examples
154    ///
155    /// ```
156    /// #![feature(once_lock_new_init)]
157    /// use std::sync::OnceLock;
158    ///
159    /// static CELL: OnceLock<i32> = OnceLock::new_init(1);
160    ///
161    /// assert_eq!(CELL.get(), Some(&1));
162    ///
163    /// // Already initialized, so this closure never runs.
164    /// assert_eq!(CELL.get_or_init(|| panic!("Kaboom!")), &1);
165    /// ```
166    #[inline]
167    #[must_use]
168    #[unstable(feature = "once_lock_new_init", issue = "159860")]
169    pub const fn new_init(init_value: T) -> OnceLock<T> {
170        OnceLock {
171            once: Once::new_complete(),
172            value: UnsafeCell::new(MaybeUninit::new(init_value)),
173            _marker: PhantomData,
174        }
175    }
176
177    /// Gets the reference to the underlying value.
178    ///
179    /// Returns `None` if the cell is uninitialized, or being initialized.
180    /// This method never blocks.
181    #[inline]
182    #[stable(feature = "once_cell", since = "1.70.0")]
183    #[rustc_should_not_be_called_on_const_items]
184    pub fn get(&self) -> Option<&T> {
185        if self.initialized() {
186            // Safe b/c checked initialized
187            Some(unsafe { self.get_unchecked() })
188        } else {
189            None
190        }
191    }
192
193    /// Gets the mutable reference to the underlying value.
194    ///
195    /// Returns `None` if the cell is uninitialized.
196    ///
197    /// This method never blocks. Since it borrows the `OnceLock` mutably,
198    /// it is statically guaranteed that no active borrows to the `OnceLock`
199    /// exist, including from other threads.
200    #[inline]
201    #[stable(feature = "once_cell", since = "1.70.0")]
202    pub fn get_mut(&mut self) -> Option<&mut T> {
203        if self.initialized_mut() {
204            // Safe b/c checked initialized and we have a unique access
205            Some(unsafe { self.get_unchecked_mut() })
206        } else {
207            None
208        }
209    }
210
211    /// Blocks the current thread until the cell is initialized.
212    ///
213    /// # Example
214    ///
215    /// Waiting for a computation on another thread to finish:
216    /// ```rust
217    /// use std::thread;
218    /// use std::sync::OnceLock;
219    ///
220    /// let value = OnceLock::new();
221    ///
222    /// thread::scope(|s| {
223    ///     s.spawn(|| value.set(1 + 1));
224    ///
225    ///     let result = value.wait();
226    ///     assert_eq!(result, &2);
227    /// })
228    /// ```
229    #[inline]
230    #[stable(feature = "once_wait", since = "1.86.0")]
231    #[rustc_should_not_be_called_on_const_items]
232    pub fn wait(&self) -> &T {
233        self.once.wait_force();
234
235        unsafe { self.get_unchecked() }
236    }
237
238    /// Initializes the contents of the cell to `value`.
239    ///
240    /// May block if another thread is currently attempting to initialize the cell. The cell is
241    /// guaranteed to contain a value when `set` returns, though not necessarily the one provided.
242    ///
243    /// Returns `Ok(())` if the cell was uninitialized and
244    /// `Err(value)` if the cell was already initialized.
245    ///
246    /// # Examples
247    ///
248    /// ```
249    /// use std::sync::OnceLock;
250    ///
251    /// static CELL: OnceLock<i32> = OnceLock::new();
252    ///
253    /// fn main() {
254    ///     assert!(CELL.get().is_none());
255    ///
256    ///     std::thread::spawn(|| {
257    ///         assert_eq!(CELL.set(92), Ok(()));
258    ///     }).join().unwrap();
259    ///
260    ///     assert_eq!(CELL.set(62), Err(62));
261    ///     assert_eq!(CELL.get(), Some(&92));
262    /// }
263    /// ```
264    #[inline]
265    #[stable(feature = "once_cell", since = "1.70.0")]
266    #[rustc_should_not_be_called_on_const_items]
267    pub fn set(&self, value: T) -> Result<(), T> {
268        match self.try_insert(value) {
269            Ok(_) => Ok(()),
270            Err((_, value)) => Err(value),
271        }
272    }
273
274    /// Initializes the contents of the cell to `value` if the cell was uninitialized,
275    /// then returns a reference to it.
276    ///
277    /// May block if another thread is currently attempting to initialize the cell. The cell is
278    /// guaranteed to contain a value when `try_insert` returns, though not necessarily the
279    /// one provided.
280    ///
281    /// Returns `Ok(&value)` if the cell was uninitialized and
282    /// `Err((&current_value, value))` if it was already initialized.
283    ///
284    /// # Examples
285    ///
286    /// ```
287    /// #![feature(once_cell_try_insert)]
288    ///
289    /// use std::sync::OnceLock;
290    ///
291    /// static CELL: OnceLock<i32> = OnceLock::new();
292    ///
293    /// fn main() {
294    ///     assert!(CELL.get().is_none());
295    ///
296    ///     std::thread::spawn(|| {
297    ///         assert_eq!(CELL.try_insert(92), Ok(&92));
298    ///     }).join().unwrap();
299    ///
300    ///     assert_eq!(CELL.try_insert(62), Err((&92, 62)));
301    ///     assert_eq!(CELL.get(), Some(&92));
302    /// }
303    /// ```
304    #[inline]
305    #[unstable(feature = "once_cell_try_insert", issue = "116693")]
306    #[rustc_should_not_be_called_on_const_items]
307    pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
308        let mut value = Some(value);
309        let res = self.get_or_init(|| value.take().unwrap());
310        match value {
311            None => Ok(res),
312            Some(value) => Err((res, value)),
313        }
314    }
315
316    /// Gets the contents of the cell, initializing it to `f()` if the cell
317    /// was uninitialized.
318    ///
319    /// Many threads may call `get_or_init` concurrently with different
320    /// initializing functions, but it is guaranteed that only one function
321    /// will be executed if the function doesn't panic.
322    ///
323    /// # Panics
324    ///
325    /// If `f()` panics, the panic is propagated to the caller, and the cell
326    /// remains uninitialized.
327    ///
328    /// It is an error to reentrantly initialize the cell from `f`. The
329    /// exact outcome is unspecified. Current implementation deadlocks, but
330    /// this may be changed to a panic in the future.
331    ///
332    /// # Examples
333    ///
334    /// ```
335    /// use std::sync::OnceLock;
336    ///
337    /// let cell = OnceLock::new();
338    /// let value = cell.get_or_init(|| 92);
339    /// assert_eq!(value, &92);
340    /// let value = cell.get_or_init(|| unreachable!());
341    /// assert_eq!(value, &92);
342    /// ```
343    #[inline]
344    #[stable(feature = "once_cell", since = "1.70.0")]
345    #[rustc_should_not_be_called_on_const_items]
346    pub fn get_or_init<F>(&self, f: F) -> &T
347    where
348        F: FnOnce() -> T,
349    {
350        match self.get_or_try_init(|| Ok::<T, !>(f())) {
351            Ok(val) => val,
352        }
353    }
354
355    /// Gets the mutable reference of the contents of the cell, initializing
356    /// it to `f()` if the cell was uninitialized.
357    ///
358    /// This method never blocks. Since it borrows the `OnceLock` mutably,
359    /// it is statically guaranteed that no active borrows to the `OnceLock`
360    /// exist, including from other threads.
361    ///
362    /// # Panics
363    ///
364    /// If `f()` panics, the panic is propagated to the caller, and the cell
365    /// remains uninitialized.
366    ///
367    /// # Examples
368    ///
369    /// ```
370    /// #![feature(once_cell_get_mut)]
371    ///
372    /// use std::sync::OnceLock;
373    ///
374    /// let mut cell = OnceLock::new();
375    /// let value = cell.get_mut_or_init(|| 92);
376    /// assert_eq!(*value, 92);
377    ///
378    /// *value += 2;
379    /// assert_eq!(*value, 94);
380    ///
381    /// let value = cell.get_mut_or_init(|| unreachable!());
382    /// assert_eq!(*value, 94);
383    /// ```
384    #[inline]
385    #[unstable(feature = "once_cell_get_mut", issue = "121641")]
386    pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T
387    where
388        F: FnOnce() -> T,
389    {
390        match self.get_mut_or_try_init(|| Ok::<T, !>(f())) {
391            Ok(val) => val,
392        }
393    }
394
395    /// Gets the contents of the cell, initializing it to `f()` if
396    /// the cell was uninitialized. If the cell was uninitialized
397    /// and `f()` failed, an error is returned.
398    ///
399    /// # Panics
400    ///
401    /// If `f()` panics, the panic is propagated to the caller, and
402    /// the cell remains uninitialized.
403    ///
404    /// It is an error to reentrantly initialize the cell from `f`.
405    /// The exact outcome is unspecified. Current implementation
406    /// deadlocks, but this may be changed to a panic in the future.
407    ///
408    /// # Examples
409    ///
410    /// ```
411    /// #![feature(once_cell_try)]
412    ///
413    /// use std::sync::OnceLock;
414    ///
415    /// let cell = OnceLock::new();
416    /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
417    /// assert!(cell.get().is_none());
418    /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
419    ///     Ok(92)
420    /// });
421    /// assert_eq!(value, Ok(&92));
422    /// assert_eq!(cell.get(), Some(&92))
423    /// ```
424    #[inline]
425    #[unstable(feature = "once_cell_try", issue = "109737")]
426    #[rustc_should_not_be_called_on_const_items]
427    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
428    where
429        F: FnOnce() -> Result<T, E>,
430    {
431        // Fast path check
432        // NOTE: We need to perform an acquire on the state in this method
433        // in order to correctly synchronize `LazyLock::force`. This is
434        // currently done by calling `self.get()`, which in turn calls
435        // `self.initialized()`, which in turn performs the acquire.
436        if let Some(value) = self.get() {
437            return Ok(value);
438        }
439        self.initialize(f)?;
440
441        // SAFETY: The inner value has been initialized
442        Ok(unsafe { self.get_unchecked() })
443    }
444
445    /// Gets the mutable reference of the contents of the cell, initializing
446    /// it to `f()` if the cell was uninitialized. If the cell was uninitialized
447    /// and `f()` failed, an error is returned.
448    ///
449    /// This method never blocks. Since it borrows the `OnceLock` mutably,
450    /// it is statically guaranteed that no active borrows to the `OnceLock`
451    /// exist, including from other threads.
452    ///
453    /// # Panics
454    ///
455    /// If `f()` panics, the panic is propagated to the caller, and
456    /// the cell remains uninitialized.
457    ///
458    /// # Examples
459    ///
460    /// ```
461    /// #![feature(once_cell_get_mut)]
462    ///
463    /// use std::sync::OnceLock;
464    ///
465    /// let mut cell: OnceLock<u32> = OnceLock::new();
466    ///
467    /// // Failed attempts to initialize the cell do not change its contents
468    /// assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err());
469    /// assert!(cell.get().is_none());
470    ///
471    /// let value = cell.get_mut_or_try_init(|| "1234".parse());
472    /// assert_eq!(value, Ok(&mut 1234));
473    /// *value.unwrap() += 2;
474    /// assert_eq!(cell.get(), Some(&1236))
475    /// ```
476    #[inline]
477    #[unstable(feature = "once_cell_get_mut", issue = "121641")]
478    pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
479    where
480        F: FnOnce() -> Result<T, E>,
481    {
482        if self.get_mut().is_none() {
483            self.initialize(f)?;
484        }
485
486        // SAFETY: The inner value has been initialized
487        Ok(unsafe { self.get_unchecked_mut() })
488    }
489
490    /// Consumes the `OnceLock`, returning the wrapped value. Returns
491    /// `None` if the cell was uninitialized.
492    ///
493    /// # Examples
494    ///
495    /// ```
496    /// use std::sync::OnceLock;
497    ///
498    /// let cell: OnceLock<String> = OnceLock::new();
499    /// assert_eq!(cell.into_inner(), None);
500    ///
501    /// let cell = OnceLock::new();
502    /// cell.set("hello".to_string()).unwrap();
503    /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
504    /// ```
505    #[inline]
506    #[stable(feature = "once_cell", since = "1.70.0")]
507    pub fn into_inner(mut self) -> Option<T> {
508        self.take()
509    }
510
511    /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
512    ///
513    /// Has no effect and returns `None` if the `OnceLock` was uninitialized.
514    ///
515    /// Since this method borrows the `OnceLock` mutably, it is statically guaranteed that
516    /// no active borrows to the `OnceLock` exist, including from other threads.
517    ///
518    /// # Examples
519    ///
520    /// ```
521    /// use std::sync::OnceLock;
522    ///
523    /// let mut cell: OnceLock<String> = OnceLock::new();
524    /// assert_eq!(cell.take(), None);
525    ///
526    /// let mut cell = OnceLock::new();
527    /// cell.set("hello".to_string()).unwrap();
528    /// assert_eq!(cell.take(), Some("hello".to_string()));
529    /// assert_eq!(cell.get(), None);
530    /// ```
531    #[inline]
532    #[stable(feature = "once_cell", since = "1.70.0")]
533    pub fn take(&mut self) -> Option<T> {
534        if self.initialized_mut() {
535            self.once = Once::new();
536            // SAFETY: `self.value` is initialized and contains a valid `T`.
537            // `self.once` is reset, so `initialized()` will be false again
538            // which prevents the value from being read twice.
539            unsafe { Some(self.value.get_mut().assume_init_read()) }
540        } else {
541            None
542        }
543    }
544
545    #[inline]
546    fn initialized(&self) -> bool {
547        self.once.is_completed()
548    }
549
550    #[inline]
551    fn initialized_mut(&mut self) -> bool {
552        // `state()` does not perform an atomic load, so prefer it over `is_complete()`.
553        let state = self.once.state();
554        match state {
555            OnceExclusiveState::Complete => true,
556            _ => false,
557        }
558    }
559
560    #[cold]
561    #[optimize(size)]
562    fn initialize<F, E>(&self, f: F) -> Result<(), E>
563    where
564        F: FnOnce() -> Result<T, E>,
565    {
566        let mut res: Result<(), E> = Ok(());
567        let slot = &self.value;
568
569        // Ignore poisoning from other threads
570        // If another thread panics, then we'll be able to run our closure
571        self.once.call_once_force(|p| {
572            match f() {
573                Ok(value) => {
574                    unsafe { (&mut *slot.get()).write(value) };
575                }
576                Err(e) => {
577                    res = Err(e);
578
579                    // Treat the underlying `Once` as poisoned since we
580                    // failed to initialize our value.
581                    p.poison();
582                }
583            }
584        });
585        res
586    }
587
588    /// # Safety
589    ///
590    /// The cell must be initialized
591    #[inline]
592    unsafe fn get_unchecked(&self) -> &T {
593        debug_assert!(self.initialized());
594        unsafe { (&*self.value.get()).assume_init_ref() }
595    }
596
597    /// # Safety
598    ///
599    /// The cell must be initialized
600    #[inline]
601    unsafe fn get_unchecked_mut(&mut self) -> &mut T {
602        debug_assert!(self.initialized_mut());
603        unsafe { self.value.get_mut().assume_init_mut() }
604    }
605}
606
607// Why do we need `T: Send`?
608// Thread A creates a `OnceLock` and shares it with
609// scoped thread B, which fills the cell, which is
610// then destroyed by A. That is, destructor observes
611// a sent value.
612#[stable(feature = "once_cell", since = "1.70.0")]
613unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
614#[stable(feature = "once_cell", since = "1.70.0")]
615unsafe impl<T: Send> Send for OnceLock<T> {}
616
617#[stable(feature = "once_cell", since = "1.70.0")]
618impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
619#[stable(feature = "once_cell", since = "1.70.0")]
620impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
621
622#[stable(feature = "once_cell", since = "1.70.0")]
623#[rustc_const_unstable(feature = "const_default", issue = "143894")]
624const impl<T> Default for OnceLock<T> {
625    /// Creates a new uninitialized cell.
626    ///
627    /// # Example
628    ///
629    /// ```
630    /// use std::sync::OnceLock;
631    ///
632    /// fn main() {
633    ///     assert_eq!(OnceLock::<()>::new(), OnceLock::default());
634    /// }
635    /// ```
636    #[inline]
637    fn default() -> OnceLock<T> {
638        OnceLock::new()
639    }
640}
641
642#[stable(feature = "once_cell", since = "1.70.0")]
643impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
644    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
645        let mut d = f.debug_tuple("OnceLock");
646        match self.get() {
647            Some(v) => d.field(v),
648            None => d.field(&format_args!("<uninit>")),
649        };
650        d.finish()
651    }
652}
653
654#[stable(feature = "once_cell", since = "1.70.0")]
655impl<T: Clone> Clone for OnceLock<T> {
656    #[inline]
657    fn clone(&self) -> OnceLock<T> {
658        self.get().cloned().map_or_default(Self::from)
659    }
660}
661
662#[stable(feature = "once_cell", since = "1.70.0")]
663impl<T> From<T> for OnceLock<T> {
664    /// Creates a new cell with its contents set to `value`.
665    ///
666    /// # Example
667    ///
668    /// ```
669    /// use std::sync::OnceLock;
670    ///
671    /// # fn main() -> Result<(), i32> {
672    /// let a = OnceLock::from(3);
673    /// let b = OnceLock::new();
674    /// b.set(3)?;
675    /// assert_eq!(a, b);
676    /// Ok(())
677    /// # }
678    /// ```
679    #[inline]
680    fn from(value: T) -> Self {
681        OnceLock {
682            once: Once::new_complete(),
683            value: UnsafeCell::new(MaybeUninit::new(value)),
684            _marker: PhantomData,
685        }
686    }
687}
688
689#[stable(feature = "once_cell", since = "1.70.0")]
690impl<T: PartialEq> PartialEq for OnceLock<T> {
691    /// Equality for two `OnceLock`s.
692    ///
693    /// Two `OnceLock`s are equal if they either both contain values and their
694    /// values are equal, or if neither contains a value.
695    ///
696    /// # Examples
697    ///
698    /// ```
699    /// use std::sync::OnceLock;
700    ///
701    /// let five = OnceLock::new();
702    /// five.set(5).unwrap();
703    ///
704    /// let also_five = OnceLock::new();
705    /// also_five.set(5).unwrap();
706    ///
707    /// assert!(five == also_five);
708    ///
709    /// assert!(OnceLock::<u32>::new() == OnceLock::<u32>::new());
710    /// ```
711    #[inline]
712    fn eq(&self, other: &OnceLock<T>) -> bool {
713        self.get() == other.get()
714    }
715}
716
717#[stable(feature = "once_cell", since = "1.70.0")]
718impl<T: Eq> Eq for OnceLock<T> {}
719
720#[stable(feature = "once_cell", since = "1.70.0")]
721unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
722    #[inline]
723    fn drop(&mut self) {
724        if self.initialized_mut() {
725            // SAFETY: The cell is initialized and being dropped, so it can't
726            // be accessed again. We also don't touch the `T` other than
727            // dropping it, which validates our usage of #[may_dangle].
728            unsafe { self.value.get_mut().assume_init_drop() };
729        }
730    }
731}