Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial stabilization of once_cell #105587

Merged
merged 3 commits into from
Mar 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(once_cell)]
#![feature(lazy_cell)]
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![feature(trusted_step)]
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(once_cell)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_ssa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#![feature(int_roundings)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(once_cell)]
#![feature(strict_provenance)]
#![feature(try_blocks)]
#![recursion_limit = "256"]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#![feature(never_type)]
#![feature(type_alias_impl_trait)]
#![feature(new_uninit)]
#![feature(once_cell)]
#![feature(lazy_cell)]
#![feature(rustc_attrs)]
#![feature(negative_impls)]
#![feature(test)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(is_terminal)]
#![feature(once_cell)]
#![feature(lazy_cell)]
#![feature(decl_macro)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_error_messages/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![feature(let_chains)]
#![feature(once_cell)]
#![feature(lazy_cell)]
#![feature(rustc_attrs)]
#![feature(type_alias_impl_trait)]
#![deny(rustc::untranslatable_diagnostic)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//! even if it is stabilized or removed, *do not remove it*. Instead, move the
//! symbol to the `accepted` or `removed` modules respectively.

#![feature(once_cell)]
#![feature(lazy_cell)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ This API is completely unstable and subject to change.
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(once_cell)]
#![feature(lazy_cell)]
#![feature(slice_partition_dedup)]
#![feature(try_blocks)]
#![feature(is_some_and)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![feature(decl_macro)]
#![feature(internal_output_capture)]
#![feature(thread_spawn_unchecked)]
#![feature(once_cell)]
#![feature(lazy_cell)]
#![feature(try_blocks)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#![feature(generators)]
#![feature(iter_from_generator)]
#![feature(let_chains)]
#![feature(once_cell)]
#![feature(proc_macro_internals)]
#![feature(macro_metavar_expr)]
#![feature(min_specialization)]
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
#![feature(never_type)]
#![feature(extern_types)]
#![feature(new_uninit)]
#![feature(once_cell)]
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(trusted_len)]
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_mir_build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#![feature(if_let_guard)]
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(once_cell)]
#![feature(try_blocks)]
#![recursion_limit = "256"]

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_mir_dataflow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#![feature(exact_size_is_empty)]
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(once_cell)]
#![feature(stmt_expr_attributes)]
#![feature(trusted_step)]
#![recursion_limit = "256"]
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#![feature(map_try_insert)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(once_cell)]
#![feature(option_get_or_insert_default)]
#![feature(trusted_step)]
#![feature(try_blocks)]
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_query_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#![feature(const_mut_refs)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(once_cell)]
#![feature(rustc_attrs)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(once_cell)]
#![feature(lazy_cell)]
#![feature(option_get_or_insert_default)]
#![feature(rustc_attrs)]
#![feature(map_many_mut)]
Expand Down
1 change: 0 additions & 1 deletion library/alloc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
#![feature(slice_flatten)]
#![feature(thin_box)]
#![feature(strict_provenance)]
#![feature(once_cell)]
#![feature(drain_keep_rest)]
#![deny(fuzzy_provenance_casts)]
#![deny(unsafe_op_in_unsafe_fn)]
Expand Down
97 changes: 70 additions & 27 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,77 @@
//! mutate it.
//!
//! Shareable mutable containers exist to permit mutability in a controlled manner, even in the
//! presence of aliasing. Both [`Cell<T>`] and [`RefCell<T>`] allow doing this in a single-threaded
//! way. However, neither `Cell<T>` nor `RefCell<T>` are thread safe (they do not implement
//! [`Sync`]). If you need to do aliasing and mutation between multiple threads it is possible to
//! use [`Mutex<T>`], [`RwLock<T>`] or [`atomic`] types.
//! presence of aliasing. [`Cell<T>`], [`RefCell<T>`], and [`OnceCell<T>`] allow doing this in
//! a single-threaded way—they do not implement [`Sync`]. (If you need to do aliasing and
//! mutation among multiple threads, [`Mutex<T>`], [`RwLock<T>`], [`OnceLock<T>`] or [`atomic`]
//! types are the correct data structures to do so).
//!
//! Values of the `Cell<T>` and `RefCell<T>` types may be mutated through shared references (i.e.
//! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`)
//! references. We say that `Cell<T>` and `RefCell<T>` provide 'interior mutability', in contrast
//! with typical Rust types that exhibit 'inherited mutability'.
//! Values of the `Cell<T>`, `RefCell<T>`, and `OnceCell<T>` types may be mutated through shared
//! references (i.e. the common `&T` type), whereas most Rust types can only be mutated through
//! unique (`&mut T`) references. We say these cell types provide 'interior mutability'
//! (mutable via `&T`), in contrast with typical Rust types that exhibit 'inherited mutability'
//! (mutable only via `&mut T`).
//!
//! Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` implements interior
//! mutability by moving values in and out of the `Cell<T>`. To use references instead of values,
//! one must use the `RefCell<T>` type, acquiring a write lock before mutating. `Cell<T>` provides
//! methods to retrieve and change the current interior value:
//! Cell types come in three flavors: `Cell<T>`, `RefCell<T>`, and `OnceCell<T>`. Each provides
//! a different way of providing safe interior mutability.
//!
//! ## `Cell<T>`
//!
//! [`Cell<T>`] implements interior mutability by moving values in and out of the cell. That is, an
//! `&mut T` to the inner value can never be obtained, and the value itself cannot be directly
//! obtained without replacing it with something else. Both of these rules ensure that there is
//! never more than one reference pointing to the inner value. This type provides the following
//! methods:
//!
//! - For types that implement [`Copy`], the [`get`](Cell::get) method retrieves the current
//! interior value.
//! interior value by duplicating it.
//! - For types that implement [`Default`], the [`take`](Cell::take) method replaces the current
//! interior value with [`Default::default()`] and returns the replaced value.
//! - For all types, the [`replace`](Cell::replace) method replaces the current interior value and
//! returns the replaced value and the [`into_inner`](Cell::into_inner) method consumes the
//! `Cell<T>` and returns the interior value. Additionally, the [`set`](Cell::set) method
//! replaces the interior value, dropping the replaced value.
//! - All types have:
//! - [`replace`](Cell::replace): replaces the current interior value and returns the replaced
//! value.
//! - [`into_inner`](Cell::into_inner): this method consumes the `Cell<T>` and returns the
//! interior value.
//! - [`set`](Cell::set): this method replaces the interior value, dropping the replaced value.
//!
//! `Cell<T>` is typically used for more simple types where copying or moving values isn't too
//! resource intensive (e.g. numbers), and should usually be preferred over other cell types when
//! possible. For larger and non-copy types, `RefCell` provides some advantages.
//!
//! `RefCell<T>` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can
//! ## `RefCell<T>`
//!
//! [`RefCell<T>`] uses Rust's lifetimes to implement "dynamic borrowing", a process whereby one can
//! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell<T>`s are
//! tracked 'at runtime', unlike Rust's native reference types which are entirely tracked
//! statically, at compile time. Because `RefCell<T>` borrows are dynamic it is possible to attempt
//! to borrow a value that is already mutably borrowed; when this happens it results in thread
//! panic.
//! tracked at _runtime_, unlike Rust's native reference types which are entirely tracked
//! statically, at compile time.
//!
//! An immutable reference to a `RefCell`'s inner value (`&T`) can be obtained with
//! [`borrow`](`RefCell::borrow`), and a mutable borrow (`&mut T`) can be obtained with
//! [`borrow_mut`](`RefCell::borrow_mut`). When these functions are called, they first verify that
//! Rust's borrow rules will be satisfied: any number of immutable borrows are allowed or a
//! single immutable borrow is allowed, but never both. If a borrow is attempted that would violate
//! these rules, the thread will panic.
//!
//! The corresponding [`Sync`] version of `RefCell<T>` is [`RwLock<T>`].
//!
//! ## `OnceCell<T>`
//!
//! [`OnceCell<T>`] is somewhat of a hybrid of `Cell` and `RefCell` that works for values that
//! typically only need to be set once. This means that a reference `&T` can be obtained without
//! moving or copying the inner value (unlike `Cell`) but also without runtime checks (unlike
//! `RefCell`). However, its value can also not be updated once set unless you have a mutable
//! reference to the `OnceCell`.
//!
//! `OnceCell` provides the following methods:
//!
//! - [`get`](OnceCell::get): obtain a reference to the inner value
//! - [`set`](OnceCell::set): set the inner value if it is unset (returns a `Result`)
//! - [`get_or_init`](OnceCell::get_or_init): return the inner value, initializing it if needed
//! - [`get_mut`](OnceCell::get_mut): provide a mutable reference to the inner value, only available
//! if you have a mutable reference to the cell itself.
//!
//! The corresponding [`Sync`] version of `OnceCell<T>` is [`OnceLock<T>`].
//!
//!
//! # When to choose interior mutability
//!
Expand Down Expand Up @@ -188,6 +229,8 @@
//! [`Rc<T>`]: ../../std/rc/struct.Rc.html
//! [`RwLock<T>`]: ../../std/sync/struct.RwLock.html
//! [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
//! [`OnceLock<T>`]: ../../std/sync/struct.OnceLock.html
//! [`Sync`]: ../../std/marker/trait.Sync.html
//! [`atomic`]: crate::sync::atomic

#![stable(feature = "rust1", since = "1.0.0")]
Expand All @@ -202,9 +245,9 @@ use crate::ptr::{self, NonNull};
mod lazy;
mod once;

#[unstable(feature = "once_cell", issue = "74465")]
#[unstable(feature = "lazy_cell", issue = "109736")]
pub use lazy::LazyCell;
#[unstable(feature = "once_cell", issue = "74465")]
#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")]
pub use once::OnceCell;

/// A mutable memory location.
Expand Down Expand Up @@ -419,7 +462,7 @@ impl<T> Cell<T> {
mem::replace(unsafe { &mut *self.value.get() }, val)
}

/// Unwraps the value.
/// Unwraps the value, consuming the cell.
///
/// # Examples
///
Expand Down Expand Up @@ -1969,7 +2012,7 @@ impl<T> UnsafeCell<T> {
UnsafeCell { value }
}

/// Unwraps the value.
/// Unwraps the value, consuming the cell.
///
/// # Examples
///
Expand Down Expand Up @@ -2133,7 +2176,7 @@ impl<T> SyncUnsafeCell<T> {
Self { value: UnsafeCell { value } }
}

/// Unwraps the value.
/// Unwraps the value, consuming the cell.
#[inline]
pub const fn into_inner(self) -> T {
self.value.into_inner()
Expand Down
18 changes: 9 additions & 9 deletions library/core/src/cell/lazy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::ops::Deref;
/// # Examples
///
/// ```
/// #![feature(once_cell)]
/// #![feature(lazy_cell)]
///
/// use std::cell::LazyCell;
///
Expand All @@ -29,7 +29,7 @@ use crate::ops::Deref;
/// // 92
/// // 92
/// ```
#[unstable(feature = "once_cell", issue = "74465")]
#[unstable(feature = "lazy_cell", issue = "109736")]
pub struct LazyCell<T, F = fn() -> T> {
cell: OnceCell<T>,
init: Cell<Option<F>>,
Expand All @@ -41,7 +41,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
/// # Examples
///
/// ```
/// #![feature(once_cell)]
/// #![feature(lazy_cell)]
///
/// use std::cell::LazyCell;
///
Expand All @@ -52,7 +52,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
/// assert_eq!(&*lazy, "HELLO, WORLD!");
/// ```
#[inline]
#[unstable(feature = "once_cell", issue = "74465")]
#[unstable(feature = "lazy_cell", issue = "109736")]
pub const fn new(init: F) -> LazyCell<T, F> {
LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) }
}
Expand All @@ -65,7 +65,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
/// # Examples
///
/// ```
/// #![feature(once_cell)]
/// #![feature(lazy_cell)]
///
/// use std::cell::LazyCell;
///
Expand All @@ -75,7 +75,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
/// assert_eq!(&*lazy, &92);
/// ```
#[inline]
#[unstable(feature = "once_cell", issue = "74465")]
#[unstable(feature = "lazy_cell", issue = "109736")]
pub fn force(this: &LazyCell<T, F>) -> &T {
this.cell.get_or_init(|| match this.init.take() {
Some(f) => f(),
Expand All @@ -84,7 +84,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
}
}

#[unstable(feature = "once_cell", issue = "74465")]
#[unstable(feature = "lazy_cell", issue = "109736")]
impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
type Target = T;
#[inline]
Expand All @@ -93,7 +93,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
}
}

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

#[unstable(feature = "once_cell", issue = "74465")]
#[unstable(feature = "lazy_cell", issue = "109736")]
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()
Expand Down
Loading