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((¤t_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}