about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMaybe Waffle <waffle.lapkin@gmail.com>2022-06-16 19:41:40 +0400
committerMaybe Waffle <waffle.lapkin@gmail.com>2022-06-16 19:53:59 +0400
commit7c360dc117d554a11f7193505da0835c4b890c6f (patch)
tree214c085729d9636756ebc16e0f6b17e1b5802629
parent392d2728683f140f6125732240e462c43c5caff4 (diff)
downloadrust-7c360dc117d554a11f7193505da0835c4b890c6f.tar.gz
rust-7c360dc117d554a11f7193505da0835c4b890c6f.zip
Move/rename `lazy::{OnceCell, Lazy}` to `cell::{OnceCell, LazyCell}`
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_data_structures/src/sync.rs2
-rw-r--r--compiler/rustc_error_messages/src/lib.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs4
-rw-r--r--library/core/src/cell.rs8
-rw-r--r--library/core/src/cell/lazy.rs104
-rw-r--r--library/core/src/cell/once.rs283
-rw-r--r--library/core/src/lazy.rs388
-rw-r--r--library/core/tests/lazy.rs5
-rw-r--r--library/std/src/lazy/tests.rs7
11 files changed, 407 insertions, 400 deletions
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 0910e7c94ea..71699b5cf38 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -36,9 +36,9 @@ use rustc_target::abi::Size;
 
 use libc::c_uint;
 use smallvec::SmallVec;
+use std::cell::OnceCell;
 use std::cell::RefCell;
 use std::iter;
-use std::lazy::OnceCell;
 use tracing::debug;
 
 mod create_scope_map;
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index e70509f3ecc..39c7a408fb5 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -38,11 +38,11 @@ use regex::Regex;
 use tempfile::Builder as TempFileBuilder;
 
 use std::borrow::Borrow;
+use std::cell::OnceCell;
 use std::collections::BTreeSet;
 use std::ffi::OsString;
 use std::fs::{File, OpenOptions};
 use std::io::{BufWriter, Write};
-use std::lazy::OnceCell;
 use std::ops::Deref;
 use std::path::{Path, PathBuf};
 use std::process::{ExitStatus, Output, Stdio};
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index f99ca53ab25..ec3d3d49bcb 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -173,7 +173,7 @@ cfg_if! {
         pub use std::cell::RefMut as LockGuard;
         pub use std::cell::RefMut as MappedLockGuard;
 
-        pub use std::lazy::OnceCell;
+        pub use std::cell::OnceCell;
 
         use std::cell::RefCell as InnerRwLock;
         use std::cell::RefCell as InnerLock;
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index fd4b2daae9c..145fbd43ab1 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -18,7 +18,7 @@ use std::path::{Path, PathBuf};
 use tracing::{instrument, trace};
 
 #[cfg(not(parallel_compiler))]
-use std::lazy::Lazy;
+use std::cell::LazyCell as Lazy;
 #[cfg(parallel_compiler)]
 use std::lazy::SyncLazy as Lazy;
 
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 2db5f5d4071..ad85ac71fc8 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -29,9 +29,9 @@ use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc};
 
+use std::cell::LazyCell;
 use std::convert::TryInto;
 use std::iter;
-use std::lazy::Lazy;
 use std::ops::ControlFlow;
 
 /// Helper type of a temporary returned by `.for_item(...)`.
@@ -1728,7 +1728,7 @@ fn check_variances_for_type_defn<'tcx>(
     identify_constrained_generic_params(tcx, ty_predicates, None, &mut constrained_parameters);
 
     // Lazily calculated because it is only needed in case of an error.
-    let explicitly_bounded_params = Lazy::new(|| {
+    let explicitly_bounded_params = LazyCell::new(|| {
         let icx = crate::collect::ItemCtxt::new(tcx, item.def_id.to_def_id());
         hir_generics
             .predicates
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 321f2feb921..63c83ddb6f7 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -199,6 +199,14 @@ use crate::mem;
 use crate::ops::{CoerceUnsized, Deref, DerefMut};
 use crate::ptr::{self, NonNull};
 
+mod lazy;
+mod once;
+
+#[unstable(feature = "once_cell", issue = "74465")]
+pub use lazy::LazyCell;
+#[unstable(feature = "once_cell", issue = "74465")]
+pub use once::OnceCell;
+
 /// A mutable memory location.
 ///
 /// # Examples
diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs
new file mode 100644
index 00000000000..7844be5f783
--- /dev/null
+++ b/library/core/src/cell/lazy.rs
@@ -0,0 +1,104 @@
+use crate::cell::{Cell, OnceCell};
+use crate::fmt;
+use crate::ops::Deref;
+
+/// A value which is initialized on the first access.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(once_cell)]
+///
+/// use std::cell::LazyCell;
+///
+/// let lazy: LazyCell<i32> = LazyCell::new(|| {
+///     println!("initializing");
+///     92
+/// });
+/// println!("ready");
+/// println!("{}", *lazy);
+/// println!("{}", *lazy);
+///
+/// // Prints:
+/// //   ready
+/// //   initializing
+/// //   92
+/// //   92
+/// ```
+#[unstable(feature = "once_cell", issue = "74465")]
+pub struct LazyCell<T, F = fn() -> T> {
+    cell: OnceCell<T>,
+    init: Cell<Option<F>>,
+}
+
+impl<T, F> LazyCell<T, F> {
+    /// Creates a new lazy value with the given initializing function.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::cell::LazyCell;
+    ///
+    /// let hello = "Hello, World!".to_string();
+    ///
+    /// let lazy = LazyCell::new(|| hello.to_uppercase());
+    ///
+    /// assert_eq!(&*lazy, "HELLO, WORLD!");
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub const fn new(init: F) -> LazyCell<T, F> {
+        LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) }
+    }
+}
+
+impl<T, F: FnOnce() -> T> LazyCell<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.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::cell::LazyCell;
+    ///
+    /// let lazy = LazyCell::new(|| 92);
+    ///
+    /// assert_eq!(LazyCell::force(&lazy), &92);
+    /// assert_eq!(&*lazy, &92);
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn force(this: &LazyCell<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 LazyCell<T, F> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        LazyCell::force(self)
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: Default> Default for LazyCell<T> {
+    /// Creates a new lazy value using `Default` as the initializing function.
+    fn default() -> LazyCell<T> {
+        LazyCell::new(T::default)
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish()
+    }
+}
diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs
new file mode 100644
index 00000000000..3c39394dd8c
--- /dev/null
+++ b/library/core/src/cell/once.rs
@@ -0,0 +1,283 @@
+use crate::cell::UnsafeCell;
+use crate::fmt;
+use crate::mem;
+
+/// A cell which can be written to only once.
+///
+/// Unlike `RefCell`, a `OnceCell` only provides shared `&T` references to its value.
+/// Unlike `Cell`, a `OnceCell` doesn't require copying or replacing the value to access it.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(once_cell)]
+///
+/// use std::cell::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());
+/// ```
+#[unstable(feature = "once_cell", issue = "74465")]
+pub struct OnceCell<T> {
+    // Invariant: written to at most once.
+    inner: UnsafeCell<Option<T>>,
+}
+
+impl<T> OnceCell<T> {
+    /// Creates a new empty cell.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    #[must_use]
+    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.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn get(&self) -> Option<&T> {
+        // SAFETY: 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.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn get_mut(&mut self) -> Option<&mut T> {
+        self.inner.get_mut().as_mut()
+    }
+
+    /// Sets the contents of the cell to `value`.
+    ///
+    /// # Errors
+    ///
+    /// This method returns `Ok(())` if the cell was empty and `Err(value)` if
+    /// it was full.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::cell::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());
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn set(&self, value: T) -> Result<(), T> {
+        // SAFETY: Safe because we cannot have overlapping mutable borrows
+        let slot = unsafe { &*self.inner.get() };
+        if slot.is_some() {
+            return Err(value);
+        }
+
+        // SAFETY: 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.
+        let slot = unsafe { &mut *self.inner.get() };
+        *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.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::cell::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);
+    /// ```
+    #[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`. Doing
+    /// so results in a panic.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::cell::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))
+    /// ```
+    #[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>,
+    {
+        if let Some(val) = self.get() {
+            return Ok(val);
+        }
+        /// Avoid inlining the initialization closure into the common path that fetches
+        /// the already initialized value
+        #[cold]
+        fn outlined_call<F, T, E>(f: F) -> Result<T, E>
+        where
+            F: FnOnce() -> Result<T, E>,
+        {
+            f()
+        }
+        let val = outlined_call(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 cell, returning the wrapped value.
+    ///
+    /// Returns `None` if the cell was empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::cell::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()));
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    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()
+    }
+
+    /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
+    ///
+    /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
+    ///
+    /// Safety is guaranteed by requiring a mutable reference.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::cell::OnceCell;
+    ///
+    /// let mut cell: OnceCell<String> = OnceCell::new();
+    /// assert_eq!(cell.take(), None);
+    ///
+    /// let mut cell = OnceCell::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()
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T> Default for OnceCell<T> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+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)"),
+        }
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+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
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: PartialEq> PartialEq for OnceCell<T> {
+    fn eq(&self, other: &Self) -> bool {
+        self.get() == other.get()
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: Eq> Eq for OnceCell<T> {}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T> const From<T> for OnceCell<T> {
+    /// Creates a new `OnceCell<T>` which already contains the given `value`.
+    fn from(value: T) -> Self {
+        OnceCell { inner: UnsafeCell::new(Some(value)) }
+    }
+}
diff --git a/library/core/src/lazy.rs b/library/core/src/lazy.rs
index 88826782a3d..f8c06c3f9ae 100644
--- a/library/core/src/lazy.rs
+++ b/library/core/src/lazy.rs
@@ -1,389 +1 @@
 //! Lazy values and one-time initialization of static data.
-
-use crate::cell::{Cell, UnsafeCell};
-use crate::fmt;
-use crate::mem;
-use crate::ops::Deref;
-
-/// A cell which can be written to only once.
-///
-/// Unlike `RefCell`, a `OnceCell` only provides shared `&T` references to its value.
-/// Unlike `Cell`, a `OnceCell` doesn't require copying or replacing the value to access it.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(once_cell)]
-///
-/// 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());
-/// ```
-#[unstable(feature = "once_cell", issue = "74465")]
-pub struct OnceCell<T> {
-    // Invariant: written to at most once.
-    inner: UnsafeCell<Option<T>>,
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T> Default for OnceCell<T> {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-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)"),
-        }
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-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
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: PartialEq> PartialEq for OnceCell<T> {
-    fn eq(&self, other: &Self) -> bool {
-        self.get() == other.get()
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: Eq> Eq for OnceCell<T> {}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T> const From<T> for OnceCell<T> {
-    /// Creates a new `OnceCell<T>` which already contains the given `value`.
-    fn from(value: T) -> Self {
-        OnceCell { inner: UnsafeCell::new(Some(value)) }
-    }
-}
-
-impl<T> OnceCell<T> {
-    /// Creates a new empty cell.
-    #[unstable(feature = "once_cell", issue = "74465")]
-    #[must_use]
-    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.
-    #[unstable(feature = "once_cell", issue = "74465")]
-    pub fn get(&self) -> Option<&T> {
-        // SAFETY: 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.
-    #[unstable(feature = "once_cell", issue = "74465")]
-    pub fn get_mut(&mut self) -> Option<&mut T> {
-        self.inner.get_mut().as_mut()
-    }
-
-    /// Sets the contents of the cell to `value`.
-    ///
-    /// # Errors
-    ///
-    /// This method returns `Ok(())` if the cell was empty and `Err(value)` if
-    /// it was full.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// 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());
-    /// ```
-    #[unstable(feature = "once_cell", issue = "74465")]
-    pub fn set(&self, value: T) -> Result<(), T> {
-        // SAFETY: Safe because we cannot have overlapping mutable borrows
-        let slot = unsafe { &*self.inner.get() };
-        if slot.is_some() {
-            return Err(value);
-        }
-
-        // SAFETY: 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.
-        let slot = unsafe { &mut *self.inner.get() };
-        *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.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// 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);
-    /// ```
-    #[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`. Doing
-    /// so results in a panic.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// 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))
-    /// ```
-    #[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>,
-    {
-        if let Some(val) = self.get() {
-            return Ok(val);
-        }
-        /// Avoid inlining the initialization closure into the common path that fetches
-        /// the already initialized value
-        #[cold]
-        fn outlined_call<F, T, E>(f: F) -> Result<T, E>
-        where
-            F: FnOnce() -> Result<T, E>,
-        {
-            f()
-        }
-        let val = outlined_call(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 cell, returning the wrapped value.
-    ///
-    /// Returns `None` if the cell was empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// 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()));
-    /// ```
-    #[unstable(feature = "once_cell", issue = "74465")]
-    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()
-    }
-
-    /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
-    ///
-    /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
-    ///
-    /// Safety is guaranteed by requiring a mutable reference.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::OnceCell;
-    ///
-    /// let mut cell: OnceCell<String> = OnceCell::new();
-    /// assert_eq!(cell.take(), None);
-    ///
-    /// let mut cell = OnceCell::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()
-    }
-}
-
-/// A value which is initialized on the first access.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(once_cell)]
-///
-/// use std::lazy::Lazy;
-///
-/// let lazy: Lazy<i32> = Lazy::new(|| {
-///     println!("initializing");
-///     92
-/// });
-/// println!("ready");
-/// println!("{}", *lazy);
-/// println!("{}", *lazy);
-///
-/// // Prints:
-/// //   ready
-/// //   initializing
-/// //   92
-/// //   92
-/// ```
-#[unstable(feature = "once_cell", issue = "74465")]
-pub struct Lazy<T, F = fn() -> T> {
-    cell: OnceCell<T>,
-    init: Cell<Option<F>>,
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: fmt::Debug, F> 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.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// # fn main() {
-    /// use std::lazy::Lazy;
-    ///
-    /// let hello = "Hello, World!".to_string();
-    ///
-    /// let lazy = Lazy::new(|| hello.to_uppercase());
-    ///
-    /// assert_eq!(&*lazy, "HELLO, WORLD!");
-    /// # }
-    /// ```
-    #[unstable(feature = "once_cell", issue = "74465")]
-    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.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::Lazy;
-    ///
-    /// let lazy = Lazy::new(|| 92);
-    ///
-    /// assert_eq!(Lazy::force(&lazy), &92);
-    /// assert_eq!(&*lazy, &92);
-    /// ```
-    #[unstable(feature = "once_cell", issue = "74465")]
-    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"),
-        })
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
-    type Target = T;
-    fn deref(&self) -> &T {
-        Lazy::force(self)
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-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)
-    }
-}
diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs
index 416d2b2dae4..70fcc6d2d4b 100644
--- a/library/core/tests/lazy.rs
+++ b/library/core/tests/lazy.rs
@@ -1,6 +1,5 @@
 use core::{
-    cell::Cell,
-    lazy::{Lazy, OnceCell},
+    cell::{Cell, LazyCell, OnceCell},
     sync::atomic::{AtomicUsize, Ordering::SeqCst},
 };
 
@@ -91,7 +90,7 @@ fn into_inner() {
 #[test]
 fn lazy_new() {
     let called = Cell::new(0);
-    let x = Lazy::new(|| {
+    let x = LazyCell::new(|| {
         called.set(called.get() + 1);
         92
     });
diff --git a/library/std/src/lazy/tests.rs b/library/std/src/lazy/tests.rs
index 83466eb0904..66d6236c111 100644
--- a/library/std/src/lazy/tests.rs
+++ b/library/std/src/lazy/tests.rs
@@ -1,5 +1,6 @@
 use crate::{
-    lazy::{Lazy, SyncLazy, SyncOnceCell},
+    cell::LazyCell,
+    lazy::{SyncLazy, SyncOnceCell},
     panic,
     sync::{
         atomic::{AtomicUsize, Ordering::SeqCst},
@@ -21,7 +22,7 @@ fn lazy_default() {
         }
     }
 
-    let lazy: Lazy<Mutex<Foo>> = <_>::default();
+    let lazy: LazyCell<Mutex<Foo>> = <_>::default();
 
     assert_eq!(CALLED.load(SeqCst), 0);
 
@@ -36,7 +37,7 @@ fn lazy_default() {
 
 #[test]
 fn lazy_poisoning() {
-    let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
+    let x: LazyCell<String> = LazyCell::new(|| panic!("kaboom"));
     for _ in 0..2 {
         let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len()));
         assert!(res.is_err());