about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorAleksey Kladov <aleksey.kladov@gmail.com>2020-01-12 18:14:29 +0100
committerAshley Mannix <ashleymannix@live.com.au>2020-07-17 07:23:49 +1000
commitcac1768b03c8d6673c51605dca03997876979d68 (patch)
treebde94ac2ff3a01bc28a45b4737614d5485e02027 /src/libstd
parent6ee1b62c811a6eb68d6db6dfb91f66a49956749b (diff)
downloadrust-cac1768b03c8d6673c51605dca03997876979d68.tar.gz
rust-cac1768b03c8d6673c51605dca03997876979d68.zip
First cut of `std::lazy` module
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/lazy.rs1002
-rw-r--r--src/libstd/lib.rs6
2 files changed, 1008 insertions, 0 deletions
diff --git a/src/libstd/lazy.rs b/src/libstd/lazy.rs
new file mode 100644
index 00000000000..bcac2dc311a
--- /dev/null
+++ b/src/libstd/lazy.rs
@@ -0,0 +1,1002 @@
+//! `lazy` modules provides lazy values and one-time initialization of static data.
+//!
+//! `lazy` provides two new cell-like types, `OnceCell` and `SyncOnceCell`. `OnceCell`
+//! might store arbitrary non-`Copy` types, can be assigned to at most once and provide direct access
+//! to the stored contents. In a nutshell, API looks *roughly* like this:
+//!
+//! ```rust,ignore
+//! impl<T> OnceCell<T> {
+//!     fn new() -> OnceCell<T> { ... }
+//!     fn set(&self, value: T) -> Result<(), T> { ... }
+//!     fn get(&self) -> Option<&T> { ... }
+//! }
+//! ```
+//!
+//! Note that, like with `RefCell` and `Mutex`, the `set` method requires only a shared reference.
+//! Because of the single assignment restriction `get` can return an `&T` instead of `Ref<T>`
+//! or `MutexGuard<T>`.
+//!
+//! The `SyncOnceCell` flavor is thread-safe (that is, implements [`Sync`]) trait, while  `OnceCell` one is not.
+//!
+//! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
+//!
+//! # Patterns
+//!
+//! `OnceCell` might be useful for a variety of patterns.
+//!
+//! ## Safe Initialization of global data
+//!
+//! ```rust
+//! use std::{env, io};
+//! use std::lazy::SyncOnceCell;
+//!
+//! #[derive(Debug)]
+//! pub struct Logger {
+//!     // ...
+//! }
+//! static INSTANCE: OnceCell<Logger> = OnceCell::new();
+//!
+//! impl Logger {
+//!     pub fn global() -> &'static Logger {
+//!         INSTANCE.get().expect("logger is not initialized")
+//!     }
+//!
+//!     fn from_cli(args: env::Args) -> Result<Logger, std::io::Error> {
+//!        // ...
+//! #      Ok(Logger {})
+//!     }
+//! }
+//!
+//! fn main() {
+//!     let logger = Logger::from_cli(env::args()).unwrap();
+//!     INSTANCE.set(logger).unwrap();
+//!     // use `Logger::global()` from now on
+//! }
+//! ```
+//!
+//! ## Lazy initialized global data
+//!
+//! This is essentially `lazy_static!` macro, but without a macro.
+//!
+//! ```rust
+//! use std::{sync::Mutex, collections::HashMap};
+//! use lazy::SyncOnceCell;
+//!
+//! fn global_data() -> &'static Mutex<HashMap<i32, String>> {
+//!     static INSTANCE: OnceCell<Mutex<HashMap<i32, String>>> = OnceCell::new();
+//!     INSTANCE.get_or_init(|| {
+//!         let mut m = HashMap::new();
+//!         m.insert(13, "Spica".to_string());
+//!         m.insert(74, "Hoyten".to_string());
+//!         Mutex::new(m)
+//!     })
+//! }
+//! ```
+//!
+//! There are also `sync::Lazy` and `unsync::Lazy` convenience types to streamline this pattern:
+//!
+//! ```rust
+//! use std::{sync::Mutex, collections::HashMap};
+//! use lazy::SyncLazy;
+//!
+//! static GLOBAL_DATA: Lazy<Mutex<HashMap<i32, String>>> = Lazy::new(|| {
+//!     let mut m = HashMap::new();
+//!     m.insert(13, "Spica".to_string());
+//!     m.insert(74, "Hoyten".to_string());
+//!     Mutex::new(m)
+//! });
+//!
+//! fn main() {
+//!     println!("{:?}", GLOBAL_DATA.lock().unwrap());
+//! }
+//! ```
+//!
+//! ## General purpose lazy evaluation
+//!
+//! `Lazy` also works with local variables.
+//!
+//! ```rust
+//! use std::lazy::Lazy;
+//!
+//! fn main() {
+//!     let ctx = vec![1, 2, 3];
+//!     let thunk = Lazy::new(|| {
+//!         ctx.iter().sum::<i32>()
+//!     });
+//!     assert_eq!(*thunk, 6);
+//! }
+//! ```
+//!
+//! If you need a lazy field in a struct, you probably should use `OnceCell`
+//! directly, because that will allow you to access `self` during initialization.
+//!
+//! ```rust
+//! use std::{fs, path::PathBuf};
+//!
+//! use std::lazy::OnceCell;
+//!
+//! struct Ctx {
+//!     config_path: PathBuf,
+//!     config: OnceCell<String>,
+//! }
+//!
+//! impl Ctx {
+//!     pub fn get_config(&self) -> Result<&str, std::io::Error> {
+//!         let cfg = self.config.get_or_try_init(|| {
+//!             fs::read_to_string(&self.config_path)
+//!         })?;
+//!         Ok(cfg.as_str())
+//!     }
+//! }
+//! ```
+//!
+//! ## Building block
+//!
+//! Naturally, it is  possible to build other abstractions on top of `OnceCell`.
+//! For example, this is a `regex!` macro which takes a string literal and returns an
+//! *expression* that evaluates to a `&'static Regex`:
+//!
+//! ```
+//! macro_rules! regex {
+//!     ($re:literal $(,)?) => {{
+//!         static RE: std::lazy::SyncOnceCell<regex::Regex> = std::lazy::SyncOnceCell::new();
+//!         RE.get_or_init(|| regex::Regex::new($re).unwrap())
+//!     }};
+//! }
+//! ```
+//!
+//! This macro can be useful to avoid "compile regex on every loop iteration" problem.
+//!
+//! # Comparison with other interior mutatbility types
+//!
+//! |`!Sync` types         | Access Mode            | Drawbacks                                     |
+//! |----------------------|------------------------|-----------------------------------------------|
+//! |`Cell<T>`             | `T`                    | requires `T: Copy` for `get`                  |
+//! |`RefCell<T>`          | `RefMut<T>` / `Ref<T>` | may panic at runtime                          |
+//! |`OnceCell<T>`         | `&T`                   | assignable only once                          |
+//!
+//! |`Sync` types          | Access Mode            | Drawbacks                                     |
+//! |----------------------|------------------------|-----------------------------------------------|
+//! |`AtomicT`             | `T`                    | works only with certain `Copy` types          |
+//! |`Mutex<T>`            | `MutexGuard<T>`        | may deadlock at runtime, may block the thread |
+//! |`SyncOnceCell<T>`     | `&T`                   | assignable only once, may block the thread    |
+//!
+//! Technically, calling `get_or_init` will also cause a panic or a deadlock if it recursively calls
+//! itself. However, because the assignment can happen only once, such cases should be more rare than
+//! equivalents with `RefCell` and `Mutex`.
+
+use crate::{
+    cell::{Cell, UnsafeCell},
+    fmt,
+    hint::unreachable_unchecked,
+    marker::PhantomData,
+    ops::Deref,
+    panic::{RefUnwindSafe, UnwindSafe},
+    sync::atomic::{AtomicBool, AtomicUsize, Ordering},
+    thread::{self, Thread},
+};
+
+/// A cell which can be written to only once. Not thread safe.
+///
+/// Unlike `:td::cell::RefCell`, a `OnceCell` provides simple `&`
+/// references to the contents.
+///
+/// # Example
+/// ```
+/// use std::lazy::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());
+/// ```
+pub struct OnceCell<T> {
+    // Invariant: written to at most once.
+    inner: UnsafeCell<Option<T>>,
+}
+
+// Similarly to a `Sync` bound on `SyncOnceCell`, we can use
+// `&OnceCell` to sneak a `T` through `catch_unwind`,
+// by initializing the cell in closure and extracting the value in the
+// `Drop`.
+#[cfg(feature = "std")]
+impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceCell<T> {}
+#[cfg(feature = "std")]
+impl<T: UnwindSafe> UnwindSafe for OnceCell<T> {}
+
+impl<T> Default for OnceCell<T> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.get() {
+            Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
+            None => f.write_str("OnceCell(Uninit)"),
+        }
+    }
+}
+
+impl<T: Clone> Clone for OnceCell<T> {
+    fn clone(&self) -> OnceCell<T> {
+        let res = OnceCell::new();
+        if let Some(value) = self.get() {
+            match res.set(value.clone()) {
+                Ok(()) => (),
+                Err(_) => unreachable!(),
+            }
+        }
+        res
+    }
+}
+
+impl<T: PartialEq> PartialEq for OnceCell<T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.get() == other.get()
+    }
+}
+
+impl<T: Eq> Eq for OnceCell<T> {}
+
+impl<T> From<T> for OnceCell<T> {
+    fn from(value: T) -> Self {
+        OnceCell { inner: UnsafeCell::new(Some(value)) }
+    }
+}
+
+impl<T> OnceCell<T> {
+    /// Creates a new empty cell.
+    pub const fn new() -> OnceCell<T> {
+        OnceCell { inner: UnsafeCell::new(None) }
+    }
+
+    /// Gets the reference to the underlying value.
+    ///
+    /// Returns `None` if the cell is empty.
+    pub fn get(&self) -> Option<&T> {
+        // 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 empty.
+    pub fn get_mut(&mut self) -> Option<&mut T> {
+        // Safe because we have unique access
+        unsafe { &mut *self.inner.get() }.as_mut()
+    }
+
+    /// Sets the contents of this cell to `value`.
+    ///
+    /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
+    /// full.
+    ///
+    /// # Example
+    /// ```
+    /// use std::lazy::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());
+    /// ```
+    pub fn set(&self, value: T) -> Result<(), T> {
+        let slot = unsafe { &*self.inner.get() };
+        if slot.is_some() {
+            return Err(value);
+        }
+        let slot = unsafe { &mut *self.inner.get() };
+        // 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.
+        *slot = Some(value);
+        Ok(())
+    }
+
+    /// Gets the contents of the cell, initializing it with `f`
+    /// if the cell was empty.
+    ///
+    /// # 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.
+    ///
+    /// # Example
+    /// ```
+    /// use std::lazy::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);
+    /// ```
+    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`. Doing
+    /// so results in a panic.
+    ///
+    /// # Example
+    /// ```
+    /// use std::lazy::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<i32, ()> {
+    ///     Ok(92)
+    /// });
+    /// assert_eq!(value, Ok(&92));
+    /// assert_eq!(cell.get(), Some(&92))
+    /// ```
+    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
+    where
+        F: FnOnce() -> Result<T, E>,
+    {
+        if let Some(val) = self.get() {
+            return Ok(val);
+        }
+        let val = f()?;
+        // Note that *some* forms of reentrant initialization might lead to
+        // UB (see `reentrant_init` test). I believe that just removing this
+        // `assert`, while keeping `set/get` would be sound, but it seems
+        // better to panic, rather than to silently use an old value.
+        assert!(self.set(val).is_ok(), "reentrant init");
+        Ok(self.get().unwrap())
+    }
+
+    /// Consumes the `OnceCell`, returning the wrapped value.
+    ///
+    /// Returns `None` if the cell was empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::lazy::OnceCell;
+    ///
+    /// let cell: OnceCell<String> = OnceCell::new();
+    /// assert_eq!(cell.into_inner(), None);
+    ///
+    /// let cell = OnceCell::new();
+    /// cell.set("hello".to_string()).unwrap();
+    /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
+    /// ```
+    pub fn into_inner(self) -> Option<T> {
+        // 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<T>`.
+        self.inner.into_inner()
+    }
+}
+
+/// A value which is initialized on the first access.
+///
+/// # Example
+/// ```
+/// use std::lazy::Lazy;
+///
+/// let lazy: Lazy<i32> = Lazy::new(|| {
+///     println!("initializing");
+///     92
+/// });
+/// println!("ready");
+/// println!("{}", *lazy);
+/// println!("{}", *lazy);
+///
+/// // Prints:
+/// //   ready
+/// //   initializing
+/// //   92
+/// //   92
+/// ```
+pub struct Lazy<T, F = fn() -> T> {
+    cell: OnceCell<T>,
+    init: Cell<Option<F>>,
+}
+
+#[cfg(feature = "std")]
+impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {}
+
+impl<T: fmt::Debug, F: fmt::Debug> fmt::Debug for Lazy<T, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish()
+    }
+}
+
+impl<T, F> Lazy<T, F> {
+    /// Creates a new lazy value with the given initializing function.
+    ///
+    /// # Example
+    /// ```
+    /// # fn main() {
+    /// use std::lazy::Lazy;
+    ///
+    /// let hello = "Hello, World!".to_string();
+    ///
+    /// let lazy = Lazy::new(|| hello.to_uppercase());
+    ///
+    /// assert_eq!(&*lazy, "HELLO, WORLD!");
+    /// # }
+    /// ```
+    pub const fn new(init: F) -> Lazy<T, F> {
+        Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) }
+    }
+}
+
+impl<T, F: FnOnce() -> T> Lazy<T, F> {
+    /// Forces the evaluation of this lazy value and returns a reference to
+    /// the result.
+    ///
+    /// This is equivalent to the `Deref` impl, but is explicit.
+    ///
+    /// # Example
+    /// ```
+    /// use std::lazy::Lazy;
+    ///
+    /// let lazy = Lazy::new(|| 92);
+    ///
+    /// assert_eq!(Lazy::force(&lazy), &92);
+    /// assert_eq!(&*lazy, &92);
+    /// ```
+    pub fn force(this: &Lazy<T, F>) -> &T {
+        this.cell.get_or_init(|| match this.init.take() {
+            Some(f) => f(),
+            None => panic!("Lazy instance has previously been poisoned"),
+        })
+    }
+}
+
+impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        Lazy::force(self)
+    }
+}
+
+impl<T: Default> Default for Lazy<T> {
+    /// Creates a new lazy value using `Default` as the initializing function.
+    fn default() -> Lazy<T> {
+        Lazy::new(T::default)
+    }
+}
+
+/// A thread-safe cell which can be written to only once.
+///
+/// `OnceCell` provides `&` references to the contents without RAII guards.
+///
+/// Reading a non-`None` value out of `OnceCell` establishes a
+/// happens-before relationship with a corresponding write. For example, if
+/// thread A initializes the cell with `get_or_init(f)`, and thread B
+/// subsequently reads the result of this call, B also observes all the side
+/// effects of `f`.
+///
+/// # Example
+/// ```
+/// use std::lazy::SyncOnceCell;
+///
+/// static CELL: OnceCell<String> = OnceCell::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!");
+/// ```
+pub struct SyncOnceCell<T> {
+    // This `state` word is actually an encoded version of just a pointer to a
+    // `Waiter`, so we add the `PhantomData` appropriately.
+    state_and_queue: AtomicUsize,
+    _marker: PhantomData<*mut Waiter>,
+    // FIXME: switch to `std::mem::MaybeUninit` once we are ready to bump MSRV
+    // that far. It was stabilized in 1.36.0, so, if you are reading this and
+    // it's higher than 1.46.0 outside, please send a PR! ;) (and do the same
+    // for `Lazy`, while we are at it).
+    pub(crate) value: UnsafeCell<Option<T>>,
+}
+
+// Why do we need `T: Send`?
+// Thread A creates a `OnceCell` and shares it with
+// scoped thread B, which fills the cell, which is
+// then destroyed by A. That is, destructor observes
+// a sent value.
+unsafe impl<T: Sync + Send> Sync for SyncOnceCell<T> {}
+unsafe impl<T: Send> Send for SyncOnceCell<T> {}
+
+impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SyncOnceCell<T> {}
+impl<T: UnwindSafe> UnwindSafe for SyncOnceCell<T> {}
+
+impl<T> Default for SyncOnceCell<T> {
+    fn default() -> SyncOnceCell<T> {
+        SyncOnceCell::new()
+    }
+}
+
+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("SyncOnceCell").field(v).finish(),
+            None => f.write_str("SyncOnceCell(Uninit)"),
+        }
+    }
+}
+
+impl<T: Clone> Clone for SyncOnceCell<T> {
+    fn clone(&self) -> SyncOnceCell<T> {
+        let res = SyncOnceCell::new();
+        if let Some(value) = self.get() {
+            match res.set(value.clone()) {
+                Ok(()) => (),
+                Err(_) => unreachable!(),
+            }
+        }
+        res
+    }
+}
+
+impl<T> From<T> for SyncOnceCell<T> {
+    fn from(value: T) -> Self {
+        let cell = Self::new();
+        cell.get_or_init(|| value);
+        cell
+    }
+}
+
+impl<T: PartialEq> PartialEq for SyncOnceCell<T> {
+    fn eq(&self, other: &SyncOnceCell<T>) -> bool {
+        self.get() == other.get()
+    }
+}
+
+impl<T: Eq> Eq for SyncOnceCell<T> {}
+
+impl<T> SyncOnceCell<T> {
+    /// Creates a new empty cell.
+    pub const fn new() -> SyncOnceCell<T> {
+        SyncOnceCell {
+            state_and_queue: AtomicUsize::new(INCOMPLETE),
+            _marker: PhantomData,
+            value: UnsafeCell::new(None),
+        }
+    }
+
+    /// Gets the reference to the underlying value.
+    ///
+    /// Returns `None` if the cell is empty, or being initialized. This
+    /// method never blocks.
+    pub fn get(&self) -> Option<&T> {
+        if self.is_initialized() {
+            // Safe b/c checked is_initialize
+            Some(unsafe { self.get_unchecked() })
+        } else {
+            None
+        }
+    }
+
+    /// Gets the mutable reference to the underlying value.
+    ///
+    /// Returns `None` if the cell is empty.
+    pub fn get_mut(&mut self) -> Option<&mut T> {
+        // Safe b/c we have a unique access.
+        unsafe { &mut *self.value.get() }.as_mut()
+    }
+
+    /// Get the reference to the underlying value, without checking if the
+    /// cell is initialized.
+    ///
+    /// Safety:
+    ///
+    /// Caller must ensure that the cell is in initialized state, and that
+    /// the contents are acquired by (synchronized to) this thread.
+    pub unsafe fn get_unchecked(&self) -> &T {
+        debug_assert!(self.is_initialized());
+        let slot: &Option<T> = &*self.value.get();
+        match slot {
+            Some(value) => value,
+            // This unsafe does improve performance, see `examples/bench`.
+            None => {
+                debug_assert!(false);
+                unreachable_unchecked()
+            }
+        }
+    }
+
+    /// Sets the contents of this cell to `value`.
+    ///
+    /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
+    /// full.
+    ///
+    /// # Example
+    /// ```
+    /// 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));
+    /// }
+    /// ```
+    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.
+    ///
+    /// # Example
+    /// ```
+    /// 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);
+    /// ```
+    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.
+    ///
+    /// # Example
+    /// ```
+    /// 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))
+    /// ```
+    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
+    where
+        F: FnOnce() -> Result<T, E>,
+    {
+        // Fast path check
+        if let Some(value) = self.get() {
+            return Ok(value);
+        }
+        self.initialize(f)?;
+
+        // Safe b/c called initialize
+        debug_assert!(self.is_initialized());
+        Ok(unsafe { self.get_unchecked() })
+    }
+
+    /// Consumes the `SyncOnceCell`, returning the wrapped value. Returns
+    /// `None` if the cell was empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// 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()));
+    /// ```
+    pub fn into_inner(self) -> Option<T> {
+        // 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<T>`.
+        self.value.into_inner()
+    }
+
+    /// Safety: synchronizes with store to value via Release/(Acquire|SeqCst).
+    #[inline]
+    fn is_initialized(&self) -> bool {
+        // An `Acquire` load is enough because that makes all the initialization
+        // operations visible to us, and, this being a fast path, weaker
+        // ordering helps with performance. This `Acquire` synchronizes with
+        // `SeqCst` operations on the slow path.
+        self.state_and_queue.load(Ordering::Acquire) == COMPLETE
+    }
+
+    /// Safety: synchronizes with store to value via SeqCst read from state,
+    /// writes value only once because we never get to INCOMPLETE state after a
+    /// successful write.
+    #[cold]
+    fn initialize<F, E>(&self, f: F) -> Result<(), E>
+    where
+        F: FnOnce() -> Result<T, E>,
+    {
+        let mut f = Some(f);
+        let mut res: Result<(), E> = Ok(());
+        let slot = &self.value;
+        initialize_inner(&self.state_and_queue, &mut || {
+            let f = f.take().unwrap();
+            match f() {
+                Ok(value) => {
+                    unsafe { *slot.get() = Some(value) };
+                    true
+                }
+                Err(e) => {
+                    res = Err(e);
+                    false
+                }
+            }
+        });
+        res
+    }
+}
+
+// region: copy-paste
+// The following code is copied from `sync::Once`.
+// This should be uncopypasted once we decide the right way to handle panics.
+const INCOMPLETE: usize = 0x0;
+const RUNNING: usize = 0x1;
+const COMPLETE: usize = 0x2;
+
+const STATE_MASK: usize = 0x3;
+
+
+#[repr(align(4))]
+struct Waiter {
+    thread: Cell<Option<Thread>>,
+    signaled: AtomicBool,
+    next: *const Waiter,
+}
+
+struct WaiterQueue<'a> {
+    state_and_queue: &'a AtomicUsize,
+    set_state_on_drop_to: usize,
+}
+
+impl Drop for WaiterQueue<'_> {
+    fn drop(&mut self) {
+        let state_and_queue =
+            self.state_and_queue.swap(self.set_state_on_drop_to, Ordering::AcqRel);
+
+        assert_eq!(state_and_queue & STATE_MASK, RUNNING);
+
+        unsafe {
+            let mut queue = (state_and_queue & !STATE_MASK) as *const Waiter;
+            while !queue.is_null() {
+                let next = (*queue).next;
+                let thread = (*queue).thread.replace(None).unwrap();
+                (*queue).signaled.store(true, Ordering::Release);
+                queue = next;
+                thread.unpark();
+            }
+        }
+    }
+}
+
+fn initialize_inner(my_state_and_queue: &AtomicUsize, init: &mut dyn FnMut() -> bool) -> bool {
+    let mut state_and_queue = my_state_and_queue.load(Ordering::Acquire);
+
+    loop {
+        match state_and_queue {
+            COMPLETE => return true,
+            INCOMPLETE => {
+                let old = my_state_and_queue.compare_and_swap(
+                    state_and_queue,
+                    RUNNING,
+                    Ordering::Acquire,
+                );
+                if old != state_and_queue {
+                    state_and_queue = old;
+                    continue;
+                }
+                let mut waiter_queue = WaiterQueue {
+                    state_and_queue: my_state_and_queue,
+                    set_state_on_drop_to: INCOMPLETE,
+                };
+                let success = init();
+
+                waiter_queue.set_state_on_drop_to = if success { COMPLETE } else { INCOMPLETE };
+                return success;
+            }
+            _ => {
+                assert!(state_and_queue & STATE_MASK == RUNNING);
+                wait(&my_state_and_queue, state_and_queue);
+                state_and_queue = my_state_and_queue.load(Ordering::Acquire);
+            }
+        }
+    }
+}
+
+fn wait(state_and_queue: &AtomicUsize, mut current_state: usize) {
+    loop {
+        if current_state & STATE_MASK != RUNNING {
+            return;
+        }
+
+        let node = Waiter {
+            thread: Cell::new(Some(thread::current())),
+            signaled: AtomicBool::new(false),
+            next: (current_state & !STATE_MASK) as *const Waiter,
+        };
+        let me = &node as *const Waiter as usize;
+
+        let old = state_and_queue.compare_and_swap(current_state, me | RUNNING, Ordering::Release);
+        if old != current_state {
+            current_state = old;
+            continue;
+        }
+
+        while !node.signaled.load(Ordering::Acquire) {
+            thread::park();
+        }
+        break;
+    }
+}
+// endregion: copy-paste
+
+/// A value which is initialized on the first access.
+///
+/// This type is thread-safe and can be used in statics:
+///
+/// # Example
+/// ```
+/// use std::collections::HashMap;
+///
+/// use std::lazy::Lazy;
+///
+/// static HASHMAP: Lazy<HashMap<i32, String>> = Lazy::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")
+/// }
+/// ```
+pub struct SyncLazy<T, F = fn() -> T> {
+    cell: SyncOnceCell<T>,
+    init: Cell<Option<F>>,
+}
+
+impl<T: fmt::Debug, F: fmt::Debug> fmt::Debug for SyncLazy<T, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("SyncLazy").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.
+unsafe impl<T, F: Send> Sync for SyncLazy<T, F> where SyncOnceCell<T>: Sync {}
+// auto-derived `Send` impl is OK.
+
+#[cfg(feature = "std")]
+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.
+    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.
+    ///
+    /// # Example
+    /// ```
+    /// use std::lazy::SyncLazy;
+    ///
+    /// let lazy = SyncLazy::new(|| 92);
+    ///
+    /// assert_eq!(SyncLazy::force(&lazy), &92);
+    /// assert_eq!(&*lazy, &92);
+    /// ```
+    pub fn force(this: &SyncLazy<T, F>) -> &T {
+        this.cell.get_or_init(|| match this.init.take() {
+            Some(f) => f(),
+            None => panic!("SyncLazy instance has previously been poisoned"),
+        })
+    }
+}
+
+impl<T, F: FnOnce() -> T> Deref for SyncLazy<T, F> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        SyncLazy::force(self)
+    }
+}
+
+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)
+    }
+}
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 4fd5e238eea..171d6c3f64f 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -476,6 +476,12 @@ pub mod process;
 pub mod sync;
 pub mod time;
 
+#[unstable(
+    feature = "std_lazy",
+    issue = "99",
+)]
+pub mod lazy;
+
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub mod task {
     //! Types and Traits for working with asynchronous tasks.