about summary refs log tree commit diff
path: root/src/libstd/lazy.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/lazy.rs')
-rw-r--r--src/libstd/lazy.rs844
1 files changed, 844 insertions, 0 deletions
diff --git a/src/libstd/lazy.rs b/src/libstd/lazy.rs
new file mode 100644
index 00000000000..86e1cfae582
--- /dev/null
+++ b/src/libstd/lazy.rs
@@ -0,0 +1,844 @@
+//! Lazy values and one-time initialization of static data.
+
+use crate::{
+    cell::{Cell, UnsafeCell},
+    fmt,
+    mem::{self, MaybeUninit},
+    ops::{Deref, Drop},
+    panic::{RefUnwindSafe, UnwindSafe},
+    sync::Once,
+};
+
+#[doc(inline)]
+#[unstable(feature = "once_cell", issue = "74465")]
+pub use core::lazy::*;
+
+/// A synchronization primitive which can be written to only once.
+///
+/// This type is a thread-safe `OnceCell`.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(once_cell)]
+///
+/// use std::lazy::SyncOnceCell;
+///
+/// static CELL: SyncOnceCell<String> = SyncOnceCell::new();
+/// assert!(CELL.get().is_none());
+///
+/// std::thread::spawn(|| {
+///     let value: &String = CELL.get_or_init(|| {
+///         "Hello, World!".to_string()
+///     });
+///     assert_eq!(value, "Hello, World!");
+/// }).join().unwrap();
+///
+/// let value: Option<&String> = CELL.get();
+/// assert!(value.is_some());
+/// assert_eq!(value.unwrap().as_str(), "Hello, World!");
+/// ```
+#[unstable(feature = "once_cell", issue = "74465")]
+pub struct SyncOnceCell<T> {
+    once: Once,
+    // Whether or not the value is initialized is tracked by `state_and_queue`.
+    value: UnsafeCell<MaybeUninit<T>>,
+}
+
+// Why do we need `T: Send`?
+// Thread A creates a `SyncOnceCell` and shares it with
+// scoped thread B, which fills the cell, which is
+// then destroyed by A. That is, destructor observes
+// a sent value.
+#[unstable(feature = "once_cell", issue = "74465")]
+unsafe impl<T: Sync + Send> Sync for SyncOnceCell<T> {}
+#[unstable(feature = "once_cell", issue = "74465")]
+unsafe impl<T: Send> Send for SyncOnceCell<T> {}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SyncOnceCell<T> {}
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: UnwindSafe> UnwindSafe for SyncOnceCell<T> {}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T> Default for SyncOnceCell<T> {
+    fn default() -> SyncOnceCell<T> {
+        SyncOnceCell::new()
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: fmt::Debug> fmt::Debug for SyncOnceCell<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.get() {
+            Some(v) => f.debug_tuple("Once").field(v).finish(),
+            None => f.write_str("Once(Uninit)"),
+        }
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: Clone> Clone for SyncOnceCell<T> {
+    fn clone(&self) -> SyncOnceCell<T> {
+        let cell = Self::new();
+        if let Some(value) = self.get() {
+            match cell.set(value.clone()) {
+                Ok(()) => (),
+                Err(_) => unreachable!(),
+            }
+        }
+        cell
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T> From<T> for SyncOnceCell<T> {
+    fn from(value: T) -> Self {
+        let cell = Self::new();
+        match cell.set(value) {
+            Ok(()) => cell,
+            Err(_) => unreachable!(),
+        }
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: PartialEq> PartialEq for SyncOnceCell<T> {
+    fn eq(&self, other: &SyncOnceCell<T>) -> bool {
+        self.get() == other.get()
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: Eq> Eq for SyncOnceCell<T> {}
+
+impl<T> SyncOnceCell<T> {
+    /// Creates a new empty cell.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub const fn new() -> SyncOnceCell<T> {
+        SyncOnceCell { once: Once::new(), value: UnsafeCell::new(MaybeUninit::uninit()) }
+    }
+
+    /// Gets the reference to the underlying value.
+    ///
+    /// Returns `None` if the cell is empty, or being initialized. This
+    /// method never blocks.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn get(&self) -> Option<&T> {
+        if self.is_initialized() {
+            // Safe b/c checked is_initialized
+            Some(unsafe { self.get_unchecked() })
+        } else {
+            None
+        }
+    }
+
+    /// Gets the mutable reference to the underlying value.
+    ///
+    /// Returns `None` if the cell is empty. This method never blocks.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    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
+            Some(unsafe { self.get_unchecked_mut() })
+        } else {
+            None
+        }
+    }
+
+    /// Sets the contents of this cell to `value`.
+    ///
+    /// Returns `Ok(())` if the cell's value was updated.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::lazy::SyncOnceCell;
+    ///
+    /// static CELL: SyncOnceCell<i32> = SyncOnceCell::new();
+    ///
+    /// fn main() {
+    ///     assert!(CELL.get().is_none());
+    ///
+    ///     std::thread::spawn(|| {
+    ///         assert_eq!(CELL.set(92), Ok(()));
+    ///     }).join().unwrap();
+    ///
+    ///     assert_eq!(CELL.set(62), Err(62));
+    ///     assert_eq!(CELL.get(), Some(&92));
+    /// }
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn set(&self, value: T) -> Result<(), T> {
+        let mut value = Some(value);
+        self.get_or_init(|| value.take().unwrap());
+        match value {
+            None => Ok(()),
+            Some(value) => Err(value),
+        }
+    }
+
+    /// Gets the contents of the cell, initializing it with `f` if the cell
+    /// was empty.
+    ///
+    /// Many threads may call `get_or_init` concurrently with different
+    /// initializing functions, but it is guaranteed that only one function
+    /// will be executed.
+    ///
+    /// # 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`. The
+    /// exact outcome is unspecified. Current implementation deadlocks, but
+    /// this may be changed to a panic in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::lazy::SyncOnceCell;
+    ///
+    /// let cell = SyncOnceCell::new();
+    /// let value = cell.get_or_init(|| 92);
+    /// assert_eq!(value, &92);
+    /// let value = cell.get_or_init(|| unreachable!());
+    /// assert_eq!(value, &92);
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn get_or_init<F>(&self, f: F) -> &T
+    where
+        F: FnOnce() -> T,
+    {
+        match self.get_or_try_init(|| Ok::<T, !>(f())) {
+            Ok(val) => val,
+        }
+    }
+
+    /// Gets the contents of the cell, initializing it with `f` if
+    /// the cell was empty. If the cell was empty 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`.
+    /// The exact outcome is unspecified. Current implementation
+    /// deadlocks, but this may be changed to a panic in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::lazy::SyncOnceCell;
+    ///
+    /// let cell = SyncOnceCell::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))
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
+    where
+        F: FnOnce() -> Result<T, E>,
+    {
+        // Fast path check
+        // NOTE: We need to perform an acquire on the state in this method
+        // in order to correctly synchronize `SyncLazy::force`. This is
+        // currently done by calling `self.get()`, which in turn calls
+        // `self.is_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() })
+    }
+
+    /// Consumes the `SyncOnceCell`, returning the wrapped value. Returns
+    /// `None` if the cell was empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::lazy::SyncOnceCell;
+    ///
+    /// let cell: SyncOnceCell<String> = SyncOnceCell::new();
+    /// assert_eq!(cell.into_inner(), None);
+    ///
+    /// let cell = SyncOnceCell::new();
+    /// cell.set("hello".to_string()).unwrap();
+    /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn into_inner(mut self) -> Option<T> {
+        // Safety: Safe because we immediately free `self` without dropping
+        let inner = unsafe { self.take_inner() };
+
+        // Don't drop this `SyncOnceCell`. We just moved out one of the fields, but didn't set
+        // the state to uninitialized.
+        mem::ManuallyDrop::new(self);
+        inner
+    }
+
+    /// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state.
+    ///
+    /// Has no effect and returns `None` if the `SyncOnceCell` hasn't been initialized.
+    ///
+    /// Safety is guaranteed by requiring a mutable reference.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::lazy::SyncOnceCell;
+    ///
+    /// let mut cell: SyncOnceCell<String> = SyncOnceCell::new();
+    /// assert_eq!(cell.take(), None);
+    ///
+    /// let mut cell = SyncOnceCell::new();
+    /// cell.set("hello".to_string()).unwrap();
+    /// assert_eq!(cell.take(), Some("hello".to_string()));
+    /// assert_eq!(cell.get(), None);
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn take(&mut self) -> Option<T> {
+        mem::take(self).into_inner()
+    }
+
+    /// Takes the wrapped value out of a `SyncOnceCell`.
+    /// Afterwards the cell is no longer initialized.
+    ///
+    /// Safety: The cell must now be free'd WITHOUT dropping. No other usages of the cell
+    /// are valid. Only used by `into_inner` and `drop`.
+    unsafe fn take_inner(&mut self) -> Option<T> {
+        // The mutable reference guarantees there are no other threads that can observe us
+        // taking out the wrapped value.
+        // Right after this function `self` is supposed to be freed, so it makes little sense
+        // to atomically set the state to uninitialized.
+        if self.is_initialized() {
+            let value = mem::replace(&mut self.value, UnsafeCell::new(MaybeUninit::uninit()));
+            Some(value.into_inner().assume_init())
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn is_initialized(&self) -> bool {
+        self.once.is_completed()
+    }
+
+    #[cold]
+    fn initialize<F, E>(&self, f: F) -> Result<(), E>
+    where
+        F: FnOnce() -> Result<T, E>,
+    {
+        let mut res: Result<(), E> = Ok(());
+        let slot = &self.value;
+
+        // Ignore poisoning from other threads
+        // If another thread panics, then we'll be able to run our closure
+        self.once.call_once_force(|p| {
+            match f() {
+                Ok(value) => {
+                    unsafe { (&mut *slot.get()).write(value) };
+                }
+                Err(e) => {
+                    res = Err(e);
+
+                    // Treat the underlying `Once` as poisoned since we
+                    // failed to initialize our value. Calls
+                    p.poison();
+                }
+            }
+        });
+        res
+    }
+
+    /// Safety: The value must be initialized
+    unsafe fn get_unchecked(&self) -> &T {
+        debug_assert!(self.is_initialized());
+        (&*self.value.get()).get_ref()
+    }
+
+    /// Safety: The value must be initialized
+    unsafe fn get_unchecked_mut(&mut self) -> &mut T {
+        debug_assert!(self.is_initialized());
+        (&mut *self.value.get()).get_mut()
+    }
+}
+
+impl<T> Drop for SyncOnceCell<T> {
+    fn drop(&mut self) {
+        // Safety: The cell is being dropped, so it can't be accessed again
+        unsafe { self.take_inner() };
+    }
+}
+
+/// A value which is initialized on the first access.
+///
+/// This type is a thread-safe `Lazy`, and can be used in statics.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(once_cell)]
+///
+/// use std::collections::HashMap;
+///
+/// use std::lazy::SyncLazy;
+///
+/// static HASHMAP: SyncLazy<HashMap<i32, String>> = SyncLazy::new(|| {
+///     println!("initializing");
+///     let mut m = HashMap::new();
+///     m.insert(13, "Spica".to_string());
+///     m.insert(74, "Hoyten".to_string());
+///     m
+/// });
+///
+/// fn main() {
+///     println!("ready");
+///     std::thread::spawn(|| {
+///         println!("{:?}", HASHMAP.get(&13));
+///     }).join().unwrap();
+///     println!("{:?}", HASHMAP.get(&74));
+///
+///     // Prints:
+///     //   ready
+///     //   initializing
+///     //   Some("Spica")
+///     //   Some("Hoyten")
+/// }
+/// ```
+#[unstable(feature = "once_cell", issue = "74465")]
+pub struct SyncLazy<T, F = fn() -> T> {
+    cell: SyncOnceCell<T>,
+    init: Cell<Option<F>>,
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: fmt::Debug, F> fmt::Debug for SyncLazy<T, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish()
+    }
+}
+
+// We never create a `&F` from a `&SyncLazy<T, F>` so it is fine
+// to not impl `Sync` for `F`
+// we do create a `&mut Option<F>` in `force`, but this is
+// properly synchronized, so it only happens once
+// so it also does not contribute to this impl.
+#[unstable(feature = "once_cell", issue = "74465")]
+unsafe impl<T, F: Send> Sync for SyncLazy<T, F> where SyncOnceCell<T>: Sync {}
+// auto-derived `Send` impl is OK.
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T, F: RefUnwindSafe> RefUnwindSafe for SyncLazy<T, F> where SyncOnceCell<T>: RefUnwindSafe {}
+
+impl<T, F> SyncLazy<T, F> {
+    /// Creates a new lazy value with the given initializing
+    /// function.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub const fn new(f: F) -> SyncLazy<T, F> {
+        SyncLazy { cell: SyncOnceCell::new(), init: Cell::new(Some(f)) }
+    }
+}
+
+impl<T, F: FnOnce() -> T> SyncLazy<T, F> {
+    /// Forces the evaluation of this lazy value and
+    /// returns a reference to result. This is equivalent
+    /// to the `Deref` impl, but is explicit.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::lazy::SyncLazy;
+    ///
+    /// let lazy = SyncLazy::new(|| 92);
+    ///
+    /// assert_eq!(SyncLazy::force(&lazy), &92);
+    /// assert_eq!(&*lazy, &92);
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn force(this: &SyncLazy<T, F>) -> &T {
+        this.cell.get_or_init(|| match this.init.take() {
+            Some(f) => f(),
+            None => panic!("Lazy instance has previously been poisoned"),
+        })
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T, F: FnOnce() -> T> Deref for SyncLazy<T, F> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        SyncLazy::force(self)
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: Default> Default for SyncLazy<T> {
+    /// Creates a new lazy value using `Default` as the initializing function.
+    fn default() -> SyncLazy<T> {
+        SyncLazy::new(T::default)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::{
+        lazy::{Lazy, SyncLazy, SyncOnceCell},
+        panic,
+        sync::{
+            atomic::{AtomicUsize, Ordering::SeqCst},
+            mpsc::channel,
+            Mutex,
+        },
+    };
+
+    #[test]
+    fn lazy_default() {
+        static CALLED: AtomicUsize = AtomicUsize::new(0);
+
+        struct Foo(u8);
+        impl Default for Foo {
+            fn default() -> Self {
+                CALLED.fetch_add(1, SeqCst);
+                Foo(42)
+            }
+        }
+
+        let lazy: Lazy<Mutex<Foo>> = <_>::default();
+
+        assert_eq!(CALLED.load(SeqCst), 0);
+
+        assert_eq!(lazy.lock().unwrap().0, 42);
+        assert_eq!(CALLED.load(SeqCst), 1);
+
+        lazy.lock().unwrap().0 = 21;
+
+        assert_eq!(lazy.lock().unwrap().0, 21);
+        assert_eq!(CALLED.load(SeqCst), 1);
+    }
+
+    #[test]
+    fn lazy_poisoning() {
+        let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
+        for _ in 0..2 {
+            let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len()));
+            assert!(res.is_err());
+        }
+    }
+
+    // miri doesn't support threads
+    #[cfg(not(miri))]
+    fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
+        crate::thread::spawn(f).join().unwrap()
+    }
+
+    #[cfg(not(miri))]
+    fn spawn(f: impl FnOnce() + Send + 'static) {
+        let _ = crate::thread::spawn(f);
+    }
+
+    // "stub threads" for Miri
+    #[cfg(miri)]
+    fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
+        f(())
+    }
+
+    #[cfg(miri)]
+    fn spawn(f: impl FnOnce() + Send + 'static) {
+        f(())
+    }
+
+    #[test]
+    fn sync_once_cell() {
+        static ONCE_CELL: SyncOnceCell<i32> = SyncOnceCell::new();
+
+        assert!(ONCE_CELL.get().is_none());
+
+        spawn_and_wait(|| {
+            ONCE_CELL.get_or_init(|| 92);
+            assert_eq!(ONCE_CELL.get(), Some(&92));
+        });
+
+        ONCE_CELL.get_or_init(|| panic!("Kabom!"));
+        assert_eq!(ONCE_CELL.get(), Some(&92));
+    }
+
+    #[test]
+    fn sync_once_cell_get_mut() {
+        let mut c = SyncOnceCell::new();
+        assert!(c.get_mut().is_none());
+        c.set(90).unwrap();
+        *c.get_mut().unwrap() += 2;
+        assert_eq!(c.get_mut(), Some(&mut 92));
+    }
+
+    #[test]
+    fn sync_once_cell_get_unchecked() {
+        let c = SyncOnceCell::new();
+        c.set(92).unwrap();
+        unsafe {
+            assert_eq!(c.get_unchecked(), &92);
+        }
+    }
+
+    #[test]
+    fn sync_once_cell_drop() {
+        static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
+        struct Dropper;
+        impl Drop for Dropper {
+            fn drop(&mut self) {
+                DROP_CNT.fetch_add(1, SeqCst);
+            }
+        }
+
+        let x = SyncOnceCell::new();
+        spawn_and_wait(move || {
+            x.get_or_init(|| Dropper);
+            assert_eq!(DROP_CNT.load(SeqCst), 0);
+            drop(x);
+        });
+
+        assert_eq!(DROP_CNT.load(SeqCst), 1);
+    }
+
+    #[test]
+    fn sync_once_cell_drop_empty() {
+        let x = SyncOnceCell::<String>::new();
+        drop(x);
+    }
+
+    #[test]
+    fn clone() {
+        let s = SyncOnceCell::new();
+        let c = s.clone();
+        assert!(c.get().is_none());
+
+        s.set("hello".to_string()).unwrap();
+        let c = s.clone();
+        assert_eq!(c.get().map(String::as_str), Some("hello"));
+    }
+
+    #[test]
+    fn get_or_try_init() {
+        let cell: SyncOnceCell<String> = SyncOnceCell::new();
+        assert!(cell.get().is_none());
+
+        let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() }));
+        assert!(res.is_err());
+        assert!(!cell.is_initialized());
+        assert!(cell.get().is_none());
+
+        assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
+
+        assert_eq!(
+            cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())),
+            Ok(&"hello".to_string())
+        );
+        assert_eq!(cell.get(), Some(&"hello".to_string()));
+    }
+
+    #[test]
+    fn from_impl() {
+        assert_eq!(SyncOnceCell::from("value").get(), Some(&"value"));
+        assert_ne!(SyncOnceCell::from("foo").get(), Some(&"bar"));
+    }
+
+    #[test]
+    fn partialeq_impl() {
+        assert!(SyncOnceCell::from("value") == SyncOnceCell::from("value"));
+        assert!(SyncOnceCell::from("foo") != SyncOnceCell::from("bar"));
+
+        assert!(SyncOnceCell::<String>::new() == SyncOnceCell::new());
+        assert!(SyncOnceCell::<String>::new() != SyncOnceCell::from("value".to_owned()));
+    }
+
+    #[test]
+    fn into_inner() {
+        let cell: SyncOnceCell<String> = SyncOnceCell::new();
+        assert_eq!(cell.into_inner(), None);
+        let cell = SyncOnceCell::new();
+        cell.set("hello".to_string()).unwrap();
+        assert_eq!(cell.into_inner(), Some("hello".to_string()));
+    }
+
+    #[test]
+    fn sync_lazy_new() {
+        static CALLED: AtomicUsize = AtomicUsize::new(0);
+        static SYNC_LAZY: SyncLazy<i32> = SyncLazy::new(|| {
+            CALLED.fetch_add(1, SeqCst);
+            92
+        });
+
+        assert_eq!(CALLED.load(SeqCst), 0);
+
+        spawn_and_wait(|| {
+            let y = *SYNC_LAZY - 30;
+            assert_eq!(y, 62);
+            assert_eq!(CALLED.load(SeqCst), 1);
+        });
+
+        let y = *SYNC_LAZY - 30;
+        assert_eq!(y, 62);
+        assert_eq!(CALLED.load(SeqCst), 1);
+    }
+
+    #[test]
+    fn sync_lazy_default() {
+        static CALLED: AtomicUsize = AtomicUsize::new(0);
+
+        struct Foo(u8);
+        impl Default for Foo {
+            fn default() -> Self {
+                CALLED.fetch_add(1, SeqCst);
+                Foo(42)
+            }
+        }
+
+        let lazy: SyncLazy<Mutex<Foo>> = <_>::default();
+
+        assert_eq!(CALLED.load(SeqCst), 0);
+
+        assert_eq!(lazy.lock().unwrap().0, 42);
+        assert_eq!(CALLED.load(SeqCst), 1);
+
+        lazy.lock().unwrap().0 = 21;
+
+        assert_eq!(lazy.lock().unwrap().0, 21);
+        assert_eq!(CALLED.load(SeqCst), 1);
+    }
+
+    #[test]
+    #[cfg_attr(miri, ignore)] // leaks memory
+    fn static_sync_lazy() {
+        static XS: SyncLazy<Vec<i32>> = SyncLazy::new(|| {
+            let mut xs = Vec::new();
+            xs.push(1);
+            xs.push(2);
+            xs.push(3);
+            xs
+        });
+
+        spawn_and_wait(|| {
+            assert_eq!(&*XS, &vec![1, 2, 3]);
+        });
+
+        assert_eq!(&*XS, &vec![1, 2, 3]);
+    }
+
+    #[test]
+    #[cfg_attr(miri, ignore)] // leaks memory
+    fn static_sync_lazy_via_fn() {
+        fn xs() -> &'static Vec<i32> {
+            static XS: SyncOnceCell<Vec<i32>> = SyncOnceCell::new();
+            XS.get_or_init(|| {
+                let mut xs = Vec::new();
+                xs.push(1);
+                xs.push(2);
+                xs.push(3);
+                xs
+            })
+        }
+        assert_eq!(xs(), &vec![1, 2, 3]);
+    }
+
+    #[test]
+    fn sync_lazy_poisoning() {
+        let x: SyncLazy<String> = SyncLazy::new(|| panic!("kaboom"));
+        for _ in 0..2 {
+            let res = panic::catch_unwind(|| x.len());
+            assert!(res.is_err());
+        }
+    }
+
+    #[test]
+    fn is_sync_send() {
+        fn assert_traits<T: Send + Sync>() {}
+        assert_traits::<SyncOnceCell<String>>();
+        assert_traits::<SyncLazy<String>>();
+    }
+
+    #[test]
+    fn eval_once_macro() {
+        macro_rules! eval_once {
+            (|| -> $ty:ty {
+                $($body:tt)*
+            }) => {{
+                static ONCE_CELL: SyncOnceCell<$ty> = SyncOnceCell::new();
+                fn init() -> $ty {
+                    $($body)*
+                }
+                ONCE_CELL.get_or_init(init)
+            }};
+        }
+
+        let fib: &'static Vec<i32> = eval_once! {
+            || -> Vec<i32> {
+                let mut res = vec![1, 1];
+                for i in 0..10 {
+                    let next = res[i] + res[i + 1];
+                    res.push(next);
+                }
+                res
+            }
+        };
+        assert_eq!(fib[5], 8)
+    }
+
+    #[test]
+    #[cfg_attr(miri, ignore)] // deadlocks without real threads
+    fn sync_once_cell_does_not_leak_partially_constructed_boxes() {
+        static ONCE_CELL: SyncOnceCell<String> = SyncOnceCell::new();
+
+        let n_readers = 10;
+        let n_writers = 3;
+        const MSG: &str = "Hello, World";
+
+        let (tx, rx) = channel();
+
+        for _ in 0..n_readers {
+            let tx = tx.clone();
+            spawn(move || {
+                loop {
+                    if let Some(msg) = ONCE_CELL.get() {
+                        tx.send(msg).unwrap();
+                        break;
+                    }
+                }
+            });
+        }
+        for _ in 0..n_writers {
+            spawn(move || {
+                let _ = ONCE_CELL.set(MSG.to_owned());
+            });
+        }
+
+        for _ in 0..n_readers {
+            let msg = rx.recv().unwrap();
+            assert_eq!(msg, MSG);
+        }
+    }
+}