Skip to content

Commit

Permalink
Partially stabilize LazyCell and LazyLock
Browse files Browse the repository at this point in the history
This is enough for usage in `static`s and many other use-cases, but leaves the `F` parameter unstable, sidestepping the unresolved questions.

cc #109736
  • Loading branch information
pitaj committed Feb 21, 2024
1 parent 2dc0170 commit 730d4df
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 32 deletions.
21 changes: 8 additions & 13 deletions library/core/src/cell/lazy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ enum State<T, F> {
/// # Examples
///
/// ```
/// #![feature(lazy_cell)]
///
/// use std::cell::LazyCell;
///
/// let lazy: LazyCell<i32> = LazyCell::new(|| {
Expand All @@ -36,8 +34,8 @@ enum State<T, F> {
/// // 92
/// // 92
/// ```
#[unstable(feature = "lazy_cell", issue = "109736")]
pub struct LazyCell<T, F = fn() -> T> {
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
pub struct LazyCell<T, #[unstable(feature = "lazy_cell", issue = "109736")] F = fn() -> T> {
state: UnsafeCell<State<T, F>>,
}

Expand All @@ -47,8 +45,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
/// # Examples
///
/// ```
/// #![feature(lazy_cell)]
///
/// use std::cell::LazyCell;
///
/// let hello = "Hello, World!".to_string();
Expand All @@ -58,7 +54,8 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
/// assert_eq!(&*lazy, "HELLO, WORLD!");
/// ```
#[inline]
#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
pub const fn new(f: F) -> LazyCell<T, F> {
LazyCell { state: UnsafeCell::new(State::Uninit(f)) }
}
Expand Down Expand Up @@ -99,8 +96,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
/// # Examples
///
/// ```
/// #![feature(lazy_cell)]
///
/// use std::cell::LazyCell;
///
/// let lazy = LazyCell::new(|| 92);
Expand All @@ -109,7 +104,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
/// assert_eq!(&*lazy, &92);
/// ```
#[inline]
#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
pub fn force(this: &LazyCell<T, F>) -> &T {
// SAFETY:
// This invalidates any mutable references to the data. The resulting
Expand Down Expand Up @@ -173,7 +168,7 @@ impl<T, F> LazyCell<T, F> {
}
}

#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
type Target = T;
#[inline]
Expand All @@ -182,7 +177,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
}
}

#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
impl<T: Default> Default for LazyCell<T> {
/// Creates a new lazy value using `Default` as the initializing function.
#[inline]
Expand All @@ -191,7 +186,7 @@ impl<T: Default> Default for LazyCell<T> {
}
}

#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_tuple("LazyCell");
Expand Down
43 changes: 24 additions & 19 deletions library/std/src/sync/lazy_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ union Data<T, F> {
/// Initialize static variables with `LazyLock`.
///
/// ```
/// #![feature(lazy_cell)]
///
/// use std::collections::HashMap;
///
/// use std::sync::LazyLock;
Expand Down Expand Up @@ -61,8 +59,6 @@ union Data<T, F> {
/// ```
/// Initialize fields with `LazyLock`.
/// ```
/// #![feature(lazy_cell)]
///
/// use std::sync::LazyLock;
///
/// #[derive(Debug)]
Expand All @@ -76,17 +72,29 @@ union Data<T, F> {
/// println!("{}", *data.number);
/// }
/// ```

#[unstable(feature = "lazy_cell", issue = "109736")]
pub struct LazyLock<T, F = fn() -> T> {
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
pub struct LazyLock<T, #[unstable(feature = "lazy_cell", issue = "109736")] F = fn() -> T> {
once: Once,
data: UnsafeCell<Data<T, F>>,
}

impl<T, F: FnOnce() -> T> LazyLock<T, F> {
/// Creates a new lazy value with the given initializing function.
///
/// # Examples
///
/// ```
/// use std::sync::LazyLock;
///
/// let hello = "Hello, World!".to_string();
///
/// let lazy = LazyLock::new(|| hello.to_uppercase());
///
/// assert_eq!(&*lazy, "HELLO, WORLD!");
/// ```
#[inline]
#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
pub const fn new(f: F) -> LazyLock<T, F> {
LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
}
Expand All @@ -107,7 +115,6 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
/// # Examples
///
/// ```
/// #![feature(lazy_cell)]
/// #![feature(lazy_cell_consume)]
///
/// use std::sync::LazyLock;
Expand Down Expand Up @@ -145,8 +152,6 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
/// # Examples
///
/// ```
/// #![feature(lazy_cell)]
///
/// use std::sync::LazyLock;
///
/// let lazy = LazyLock::new(|| 92);
Expand All @@ -155,7 +160,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
/// assert_eq!(&*lazy, &92);
/// ```
#[inline]
#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
pub fn force(this: &LazyLock<T, F>) -> &T {
this.once.call_once(|| {
// SAFETY: `call_once` only runs this closure once, ever.
Expand Down Expand Up @@ -191,7 +196,7 @@ impl<T, F> LazyLock<T, F> {
}
}

#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
impl<T, F> Drop for LazyLock<T, F> {
fn drop(&mut self) {
match self.once.state() {
Expand All @@ -204,7 +209,7 @@ impl<T, F> Drop for LazyLock<T, F> {
}
}

#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
type Target = T;

Expand All @@ -219,7 +224,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
}
}

#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
impl<T: Default> Default for LazyLock<T> {
/// Creates a new lazy value using `Default` as the initializing function.
#[inline]
Expand All @@ -228,7 +233,7 @@ impl<T: Default> Default for LazyLock<T> {
}
}

#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_tuple("LazyLock");
Expand All @@ -242,13 +247,13 @@ impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {

// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
// to not impl `Sync` for `F`.
#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
// auto-derived `Send` impl is OK.

#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
#[unstable(feature = "lazy_cell", issue = "109736")]
#[stable(feature = "lazy_cell_fn_pointer", since = "CURRENT_RUSTC_VERSION")]
impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}

#[cfg(test)]
Expand Down

0 comments on commit 730d4df

Please sign in to comment.