From dc4ba57566acac492df2c2074d2d7144566dc7df Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 12 Dec 2022 00:42:45 -0500 Subject: [PATCH 1/3] Stabilize a portion of 'once_cell' Move items not part of this stabilization to 'lazy_cell' or 'once_cell_try' --- compiler/rustc_borrowck/src/lib.rs | 2 +- compiler/rustc_codegen_llvm/src/lib.rs | 1 - compiler/rustc_codegen_ssa/src/lib.rs | 1 - compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_driver_impl/src/lib.rs | 2 +- compiler/rustc_error_messages/src/lib.rs | 2 +- compiler/rustc_feature/src/lib.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_interface/src/lib.rs | 2 +- compiler/rustc_metadata/src/lib.rs | 1 - compiler/rustc_middle/src/lib.rs | 1 - compiler/rustc_mir_build/src/lib.rs | 1 - compiler/rustc_mir_dataflow/src/lib.rs | 1 - compiler/rustc_mir_transform/src/lib.rs | 1 - compiler/rustc_query_impl/src/lib.rs | 1 - compiler/rustc_session/src/lib.rs | 2 +- library/alloc/tests/lib.rs | 1 - library/core/src/cell.rs | 4 +- library/core/src/cell/lazy.rs | 18 +++--- library/core/src/cell/once.rs | 46 ++++++--------- library/core/tests/lib.rs | 2 +- library/std/src/lib.rs | 2 +- library/std/src/sync/lazy_lock.rs | 24 ++++---- library/std/src/sync/mod.rs | 4 +- library/std/src/sync/once_lock.rs | 59 +++++++------------ src/librustdoc/lib.rs | 2 +- src/tools/clippy/clippy_dev/src/lib.rs | 1 - src/tools/clippy/clippy_lints/src/lib.rs | 1 - src/tools/clippy/clippy_utils/src/lib.rs | 1 - src/tools/clippy/src/driver.rs | 2 +- src/tools/clippy/tests/compile-test.rs | 2 +- src/tools/clippy/tests/dogfood.rs | 2 +- .../clippy/tests/lint_message_convention.rs | 2 +- src/tools/clippy/tests/workspace.rs | 2 +- tests/run-make/libtest-thread-limit/test.rs | 2 - .../nested-closure.rs | 2 +- tests/ui/sync/suggest-once-cell.rs | 2 - tests/ui/sync/suggest-once-cell.stderr | 4 +- tests/ui/sync/suggest-ref-cell.rs | 2 - tests/ui/sync/suggest-ref-cell.stderr | 4 +- 40 files changed, 87 insertions(+), 128 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index b7ce3afce7b..9bd7cff1f33 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -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)] diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index e5bae009ed6..3f77ea77eff 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -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)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 81227b04e8a..0ab12314b3c 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -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"] diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 0339fb925d4..9b52638e612 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -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)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 1e835f6065a..b96b356f551 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -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)] diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 301dacc2824..6f319b96f2f 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -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)] diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 93d16716346..3ce16e15667 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -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)] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index d43230cb563..2a9025d60ab 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -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)] diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 15e02671075..9664ba8bd8a 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -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)] diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 98d9ad31fe0..880da5ca593 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -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)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 45c4a1057d2..0e883424fd4 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -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)] diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 04709197578..3f9236c9dd9 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -8,7 +8,6 @@ #![feature(if_let_guard)] #![feature(let_chains)] #![feature(min_specialization)] -#![feature(once_cell)] #![feature(try_blocks)] #![recursion_limit = "256"] diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 4ed6f7e90ff..43caa2ea973 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -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"] diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 3a515fe8323..6173b446b87 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -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)] diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 4cd94237061..021a67c9513 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -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)] diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 74aef785163..968728905e7 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -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)] diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 966cf575116..6387279f4c1 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -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)] diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 9d1720acf36..178927f6385 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -202,9 +202,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. diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index 65d12c25c51..64a6ce51b2e 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -11,7 +11,7 @@ use crate::ops::Deref; /// # Examples /// /// ``` -/// #![feature(once_cell)] +/// #![feature(lazy_cell)] /// /// use std::cell::LazyCell; /// @@ -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> { cell: OnceCell, init: Cell>, @@ -41,7 +41,7 @@ impl T> LazyCell { /// # Examples /// /// ``` - /// #![feature(once_cell)] + /// #![feature(lazy_cell)] /// /// use std::cell::LazyCell; /// @@ -52,7 +52,7 @@ impl T> LazyCell { /// 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 { LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) } } @@ -65,7 +65,7 @@ impl T> LazyCell { /// # Examples /// /// ``` - /// #![feature(once_cell)] + /// #![feature(lazy_cell)] /// /// use std::cell::LazyCell; /// @@ -75,7 +75,7 @@ impl T> LazyCell { /// assert_eq!(&*lazy, &92); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[unstable(feature = "lazy_cell", issue = "109736")] pub fn force(this: &LazyCell) -> &T { this.cell.get_or_init(|| match this.init.take() { Some(f) => f(), @@ -84,7 +84,7 @@ impl T> LazyCell { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl T> Deref for LazyCell { type Target = T; #[inline] @@ -93,7 +93,7 @@ impl T> Deref for LazyCell { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl Default for LazyCell { /// Creates a new lazy value using `Default` as the initializing function. #[inline] @@ -102,7 +102,7 @@ impl Default for LazyCell { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl fmt::Debug for LazyCell { 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 index f74e563f1b9..c5bd7a5fa01 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -16,8 +16,6 @@ use crate::mem; /// # Examples /// /// ``` -/// #![feature(once_cell)] -/// /// use std::cell::OnceCell; /// /// let cell = OnceCell::new(); @@ -29,7 +27,7 @@ use crate::mem; /// assert_eq!(value, "Hello, World!"); /// assert!(cell.get().is_some()); /// ``` -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub struct OnceCell { // Invariant: written to at most once. inner: UnsafeCell>, @@ -39,7 +37,8 @@ impl OnceCell { /// Creates a new empty cell. #[inline] #[must_use] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn new() -> OnceCell { OnceCell { inner: UnsafeCell::new(None) } } @@ -48,7 +47,7 @@ impl OnceCell { /// /// Returns `None` if the cell is empty. #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn get(&self) -> Option<&T> { // SAFETY: Safe due to `inner`'s invariant unsafe { &*self.inner.get() }.as_ref() @@ -58,7 +57,7 @@ impl OnceCell { /// /// Returns `None` if the cell is empty. #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn get_mut(&mut self) -> Option<&mut T> { self.inner.get_mut().as_mut() } @@ -73,8 +72,6 @@ impl OnceCell { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::cell::OnceCell; /// /// let cell = OnceCell::new(); @@ -86,7 +83,7 @@ impl OnceCell { /// assert!(cell.get().is_some()); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn set(&self, value: T) -> Result<(), T> { // SAFETY: Safe because we cannot have overlapping mutable borrows let slot = unsafe { &*self.inner.get() }; @@ -117,8 +114,6 @@ impl OnceCell { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::cell::OnceCell; /// /// let cell = OnceCell::new(); @@ -128,7 +123,7 @@ impl OnceCell { /// assert_eq!(value, &92); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, @@ -153,7 +148,7 @@ impl OnceCell { /// # Examples /// /// ``` - /// #![feature(once_cell)] + /// #![feature(once_cell_try)] /// /// use std::cell::OnceCell; /// @@ -166,7 +161,7 @@ impl OnceCell { /// assert_eq!(value, Ok(&92)); /// assert_eq!(cell.get(), Some(&92)) /// ``` - #[unstable(feature = "once_cell", issue = "74465")] + #[unstable(feature = "once_cell_try", issue = "109737")] pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, @@ -199,8 +194,6 @@ impl OnceCell { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::cell::OnceCell; /// /// let cell: OnceCell = OnceCell::new(); @@ -211,7 +204,7 @@ impl OnceCell { /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn into_inner(self) -> Option { // 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`. @@ -227,8 +220,6 @@ impl OnceCell { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::cell::OnceCell; /// /// let mut cell: OnceCell = OnceCell::new(); @@ -240,13 +231,13 @@ impl OnceCell { /// assert_eq!(cell.get(), None); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn take(&mut self) -> Option { mem::take(self).into_inner() } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl Default for OnceCell { #[inline] fn default() -> Self { @@ -254,7 +245,7 @@ impl Default for OnceCell { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for OnceCell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.get() { @@ -264,7 +255,7 @@ impl fmt::Debug for OnceCell { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl Clone for OnceCell { #[inline] fn clone(&self) -> OnceCell { @@ -279,7 +270,7 @@ impl Clone for OnceCell { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl PartialEq for OnceCell { #[inline] fn eq(&self, other: &Self) -> bool { @@ -287,10 +278,11 @@ impl PartialEq for OnceCell { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl Eq for OnceCell {} -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] impl const From for OnceCell { /// Creates a new `OnceCell` which already contains the given `value`. #[inline] @@ -300,5 +292,5 @@ impl const From for OnceCell { } // Just like for `Cell` this isn't needed, but results in nicer error messages. -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl !Sync for OnceCell {} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 108210b6573..344f0b61754 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -94,7 +94,7 @@ #![feature(pointer_is_aligned)] #![feature(portable_simd)] #![feature(ptr_metadata)] -#![feature(once_cell)] +#![feature(lazy_cell)] #![feature(unsized_tuple_coercion)] #![feature(const_option)] #![feature(const_option_ext)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index baad6de707b..8c118b95b0a 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -339,7 +339,7 @@ #![feature(edition_panic)] #![feature(format_args_nl)] #![feature(log_syntax)] -#![feature(once_cell)] +#![feature(lazy_cell)] #![feature(saturating_int_impl)] #![feature(stdsimd)] #![feature(test)] diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 7e85d6a063a..8e9ea293ce4 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -26,7 +26,7 @@ union Data { /// # Examples /// /// ``` -/// #![feature(once_cell)] +/// #![feature(lazy_cell)] /// /// use std::collections::HashMap; /// @@ -54,7 +54,7 @@ union Data { /// // Some("Hoyten") /// } /// ``` -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] pub struct LazyLock T> { once: Once, data: UnsafeCell>, @@ -64,7 +64,7 @@ impl T> LazyLock { /// Creates a new lazy value with the given initializing /// function. #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[unstable(feature = "lazy_cell", issue = "109736")] pub const fn new(f: F) -> LazyLock { LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) } } @@ -76,7 +76,7 @@ impl T> LazyLock { /// # Examples /// /// ``` - /// #![feature(once_cell)] + /// #![feature(lazy_cell)] /// /// use std::sync::LazyLock; /// @@ -86,7 +86,7 @@ impl T> LazyLock { /// assert_eq!(&*lazy, &92); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[unstable(feature = "lazy_cell", issue = "109736")] pub fn force(this: &LazyLock) -> &T { this.once.call_once(|| { // SAFETY: `call_once` only runs this closure once, ever. @@ -122,7 +122,7 @@ impl LazyLock { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl Drop for LazyLock { fn drop(&mut self) { match self.once.state() { @@ -135,7 +135,7 @@ impl Drop for LazyLock { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl T> Deref for LazyLock { type Target = T; @@ -145,7 +145,7 @@ impl T> Deref for LazyLock { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl Default for LazyLock { /// Creates a new lazy value using `Default` as the initializing function. #[inline] @@ -154,7 +154,7 @@ impl Default for LazyLock { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl fmt::Debug for LazyLock { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.get() { @@ -166,13 +166,13 @@ impl fmt::Debug for LazyLock { // We never create a `&F` from a `&LazyLock` so it is fine // to not impl `Sync` for `F` -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] unsafe impl Sync for LazyLock {} // auto-derived `Send` impl is OK. -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl RefUnwindSafe for LazyLock {} -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] impl UnwindSafe for LazyLock {} #[cfg(test)] diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 4edc956173b..5dd585b9b37 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -172,9 +172,9 @@ pub use self::poison::{LockResult, PoisonError, TryLockError, TryLockResult}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; -#[unstable(feature = "once_cell", issue = "74465")] +#[unstable(feature = "lazy_cell", issue = "109736")] pub use self::lazy_lock::LazyLock; -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub use self::once_lock::OnceLock; pub(crate) use self::remutex::{ReentrantMutex, ReentrantMutexGuard}; diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index ed339ca5df6..8c34375ea07 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -14,8 +14,6 @@ use crate::sync::Once; /// # Examples /// /// ``` -/// #![feature(once_cell)] -/// /// use std::sync::OnceLock; /// /// static CELL: OnceLock = OnceLock::new(); @@ -32,7 +30,7 @@ use crate::sync::Once; /// assert!(value.is_some()); /// assert_eq!(value.unwrap().as_str(), "Hello, World!"); /// ``` -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub struct OnceLock { once: Once, // Whether or not the value is initialized is tracked by `once.is_completed()`. @@ -40,8 +38,6 @@ pub struct OnceLock { /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl. /// /// ```compile_fail,E0597 - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// struct A<'a>(&'a str); @@ -63,7 +59,8 @@ impl OnceLock { /// Creates a new empty cell. #[inline] #[must_use] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn new() -> OnceLock { OnceLock { once: Once::new(), @@ -77,7 +74,7 @@ impl OnceLock { /// Returns `None` if the cell is empty, or being initialized. This /// method never blocks. #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn get(&self) -> Option<&T> { if self.is_initialized() { // Safe b/c checked is_initialized @@ -91,7 +88,7 @@ impl OnceLock { /// /// Returns `None` if the cell is empty. This method never blocks. #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] 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 @@ -111,8 +108,6 @@ impl OnceLock { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// static CELL: OnceLock = OnceLock::new(); @@ -129,7 +124,7 @@ impl OnceLock { /// } /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn set(&self, value: T) -> Result<(), T> { let mut value = Some(value); self.get_or_init(|| value.take().unwrap()); @@ -158,8 +153,6 @@ impl OnceLock { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// let cell = OnceLock::new(); @@ -169,7 +162,7 @@ impl OnceLock { /// assert_eq!(value, &92); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, @@ -195,7 +188,7 @@ impl OnceLock { /// # Examples /// /// ``` - /// #![feature(once_cell)] + /// #![feature(once_cell_try)] /// /// use std::sync::OnceLock; /// @@ -209,7 +202,7 @@ impl OnceLock { /// assert_eq!(cell.get(), Some(&92)) /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[unstable(feature = "once_cell_try", issue = "109737")] pub fn get_or_try_init(&self, f: F) -> Result<&T, E> where F: FnOnce() -> Result, @@ -236,8 +229,6 @@ impl OnceLock { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// let cell: OnceLock = OnceLock::new(); @@ -248,7 +239,7 @@ impl OnceLock { /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn into_inner(mut self) -> Option { self.take() } @@ -262,8 +253,6 @@ impl OnceLock { /// # Examples /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// let mut cell: OnceLock = OnceLock::new(); @@ -275,7 +264,7 @@ impl OnceLock { /// assert_eq!(cell.get(), None); /// ``` #[inline] - #[unstable(feature = "once_cell", issue = "74465")] + #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] pub fn take(&mut self) -> Option { if self.is_initialized() { self.once = Once::new(); @@ -344,17 +333,17 @@ impl OnceLock { // 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")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] unsafe impl Sync for OnceLock {} -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] unsafe impl Send for OnceLock {} -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl RefUnwindSafe for OnceLock {} -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl UnwindSafe for OnceLock {} -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] impl const Default for OnceLock { /// Creates a new empty cell. @@ -362,8 +351,6 @@ impl const Default for OnceLock { /// # Example /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// fn main() { @@ -376,7 +363,7 @@ impl const Default for OnceLock { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for OnceLock { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.get() { @@ -386,7 +373,7 @@ impl fmt::Debug for OnceLock { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl Clone for OnceLock { #[inline] fn clone(&self) -> OnceLock { @@ -401,15 +388,13 @@ impl Clone for OnceLock { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl From for OnceLock { /// Create a new cell with its contents set to `value`. /// /// # Example /// /// ``` - /// #![feature(once_cell)] - /// /// use std::sync::OnceLock; /// /// # fn main() -> Result<(), i32> { @@ -430,7 +415,7 @@ impl From for OnceLock { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl PartialEq for OnceLock { #[inline] fn eq(&self, other: &OnceLock) -> bool { @@ -438,10 +423,10 @@ impl PartialEq for OnceLock { } } -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl Eq for OnceLock {} -#[unstable(feature = "once_cell", issue = "74465")] +#[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] unsafe impl<#[may_dangle] T> Drop for OnceLock { #[inline] fn drop(&mut self) { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4fcf0873600..4c4dbc9864f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -11,7 +11,7 @@ #![feature(let_chains)] #![feature(test)] #![feature(never_type)] -#![feature(once_cell)] +#![feature(lazy_cell)] #![feature(type_ascription)] #![feature(iter_intersperse)] #![feature(type_alias_impl_trait)] diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs index e70488165b9..8871873c661 100644 --- a/src/tools/clippy/clippy_dev/src/lib.rs +++ b/src/tools/clippy/clippy_dev/src/lib.rs @@ -1,5 +1,4 @@ #![feature(let_chains)] -#![feature(once_cell)] #![feature(rustc_private)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] // warn on lints, that are included in `rust-lang/rust`s bootstrap diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index c9210bf73f8..3da7f95c1b9 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -7,7 +7,6 @@ #![feature(let_chains)] #![feature(lint_reasons)] #![feature(never_type)] -#![feature(once_cell)] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] #![recursion_limit = "512"] diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index fd06c0b8677..619aa9f4bf6 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -3,7 +3,6 @@ #![feature(let_chains)] #![feature(lint_reasons)] #![feature(never_type)] -#![feature(once_cell)] #![feature(rustc_private)] #![recursion_limit = "512"] #![cfg_attr(feature = "deny-warnings", deny(warnings))] diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index f08393c303e..9e0822404b6 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -1,6 +1,6 @@ #![feature(rustc_private)] #![feature(let_chains)] -#![feature(once_cell)] +#![feature(lazy_cell)] #![feature(lint_reasons)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] // warn on lints, that are included in `rust-lang/rust`s bootstrap diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index c10ee969c01..57890ff3173 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -1,5 +1,5 @@ #![feature(test)] // compiletest_rs requires this attribute -#![feature(once_cell)] +#![feature(lazy_cell)] #![feature(is_sorted)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs index 3a5d478fa31..68a878e9a3d 100644 --- a/src/tools/clippy/tests/dogfood.rs +++ b/src/tools/clippy/tests/dogfood.rs @@ -3,7 +3,7 @@ //! //! See [Eating your own dog food](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) for context -#![feature(once_cell)] +#![feature(lazy_cell)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/src/tools/clippy/tests/lint_message_convention.rs b/src/tools/clippy/tests/lint_message_convention.rs index abd0d1bc593..8feea800fdb 100644 --- a/src/tools/clippy/tests/lint_message_convention.rs +++ b/src/tools/clippy/tests/lint_message_convention.rs @@ -1,4 +1,4 @@ -#![feature(once_cell)] +#![feature(lazy_cell)] #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![warn(rust_2018_idioms, unused_lifetimes)] diff --git a/src/tools/clippy/tests/workspace.rs b/src/tools/clippy/tests/workspace.rs index 95325e06037..c9cbc50546c 100644 --- a/src/tools/clippy/tests/workspace.rs +++ b/src/tools/clippy/tests/workspace.rs @@ -1,4 +1,4 @@ -#![feature(once_cell)] +#![feature(lazy_cell)] use std::path::PathBuf; use std::process::Command; diff --git a/tests/run-make/libtest-thread-limit/test.rs b/tests/run-make/libtest-thread-limit/test.rs index 26bc29216cf..88e8a498ae9 100644 --- a/tests/run-make/libtest-thread-limit/test.rs +++ b/tests/run-make/libtest-thread-limit/test.rs @@ -1,5 +1,3 @@ -#![feature(once_cell)] - use std::{ io::ErrorKind, sync::OnceLock, diff --git a/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs b/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs index a851136009c..0b423b34022 100644 --- a/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs +++ b/tests/ui/rfc-2632-const-trait-impl/nested-closure.rs @@ -1,6 +1,6 @@ // check-pass -#![feature(const_trait_impl, once_cell)] +#![feature(const_trait_impl, lazy_cell)] use std::sync::LazyLock; diff --git a/tests/ui/sync/suggest-once-cell.rs b/tests/ui/sync/suggest-once-cell.rs index 82fca45b1a4..14f40ad87a3 100644 --- a/tests/ui/sync/suggest-once-cell.rs +++ b/tests/ui/sync/suggest-once-cell.rs @@ -1,5 +1,3 @@ -#![feature(once_cell)] - fn require_sync() {} //~^ NOTE required by this bound in `require_sync` //~| NOTE required by a bound in `require_sync` diff --git a/tests/ui/sync/suggest-once-cell.stderr b/tests/ui/sync/suggest-once-cell.stderr index fadf05374d8..20242f4b61c 100644 --- a/tests/ui/sync/suggest-once-cell.stderr +++ b/tests/ui/sync/suggest-once-cell.stderr @@ -1,5 +1,5 @@ error[E0277]: `OnceCell<()>` cannot be shared between threads safely - --> $DIR/suggest-once-cell.rs:8:20 + --> $DIR/suggest-once-cell.rs:6:20 | LL | require_sync::>(); | ^^^^^^^^^^^^^^^^^^^^^^^ `OnceCell<()>` cannot be shared between threads safely @@ -7,7 +7,7 @@ LL | require_sync::>(); = help: the trait `Sync` is not implemented for `OnceCell<()>` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead note: required by a bound in `require_sync` - --> $DIR/suggest-once-cell.rs:3:20 + --> $DIR/suggest-once-cell.rs:1:20 | LL | fn require_sync() {} | ^^^^ required by this bound in `require_sync` diff --git a/tests/ui/sync/suggest-ref-cell.rs b/tests/ui/sync/suggest-ref-cell.rs index 6b972ae0962..093a4999c65 100644 --- a/tests/ui/sync/suggest-ref-cell.rs +++ b/tests/ui/sync/suggest-ref-cell.rs @@ -1,5 +1,3 @@ -#![feature(once_cell)] - fn require_sync() {} //~^ NOTE required by this bound in `require_sync` //~| NOTE required by a bound in `require_sync` diff --git a/tests/ui/sync/suggest-ref-cell.stderr b/tests/ui/sync/suggest-ref-cell.stderr index 9e8b8fcb42e..ca3ae77b1a0 100644 --- a/tests/ui/sync/suggest-ref-cell.stderr +++ b/tests/ui/sync/suggest-ref-cell.stderr @@ -1,5 +1,5 @@ error[E0277]: `RefCell<()>` cannot be shared between threads safely - --> $DIR/suggest-ref-cell.rs:8:20 + --> $DIR/suggest-ref-cell.rs:6:20 | LL | require_sync::>(); | ^^^^^^^^^^^^^^^^^^^^^^ `RefCell<()>` cannot be shared between threads safely @@ -7,7 +7,7 @@ LL | require_sync::>(); = help: the trait `Sync` is not implemented for `RefCell<()>` = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead note: required by a bound in `require_sync` - --> $DIR/suggest-ref-cell.rs:3:20 + --> $DIR/suggest-ref-cell.rs:1:20 | LL | fn require_sync() {} | ^^^^ required by this bound in `require_sync` From d1b28b75d25d5f4c3d1769822a1b106b95b106f1 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 12 Dec 2022 04:16:18 -0500 Subject: [PATCH 2/3] Documentation updates to better share the purpose of OnceCell/OnceLock --- library/core/src/cell.rs | 93 +++++++++++++++++++++++++---------- library/core/src/cell/once.rs | 6 ++- library/std/src/sync/mod.rs | 5 +- 3 files changed, 76 insertions(+), 28 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 178927f6385..d378b0b3b97 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -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`] and [`RefCell`] allow doing this in a single-threaded -//! way. However, neither `Cell` nor `RefCell` 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`], [`RwLock`] or [`atomic`] types. +//! presence of aliasing. [`Cell`], [`RefCell`], and [`OnceCell`] 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`], [`RwLock`], [`OnceLock`] or [`atomic`] +//! types are the correct data structures to do so). //! -//! Values of the `Cell` and `RefCell` 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` and `RefCell` provide 'interior mutability', in contrast -//! with typical Rust types that exhibit 'inherited mutability'. +//! Values of the `Cell`, `RefCell`, and `OnceCell` 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` and `RefCell`. `Cell` implements interior -//! mutability by moving values in and out of the `Cell`. To use references instead of values, -//! one must use the `RefCell` type, acquiring a write lock before mutating. `Cell` provides -//! methods to retrieve and change the current interior value: +//! Cell types come in three flavors: `Cell`, `RefCell`, and `OnceCell`. Each provides +//! a different way of providing safe interior mutability. +//! +//! ## `Cell` +//! +//! [`Cell`] 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` 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` and returns the +//! interior value. +//! - [`set`](Cell::set): this method replaces the interior value, dropping the replaced value. //! -//! `RefCell` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can +//! `Cell` 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` +//! +//! [`RefCell`] 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`s are -//! tracked 'at runtime', unlike Rust's native reference types which are entirely tracked -//! statically, at compile time. Because `RefCell` 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` is [`RwLock`]. +//! +//! ## `OnceCell` +//! +//! [`OnceCell`] 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` is [`OnceLock`]. +//! //! //! # When to choose interior mutability //! @@ -188,6 +229,8 @@ //! [`Rc`]: ../../std/rc/struct.Rc.html //! [`RwLock`]: ../../std/sync/struct.RwLock.html //! [`Mutex`]: ../../std/sync/struct.Mutex.html +//! [`OnceLock`]: ../../std/sync/struct.OnceLock.html +//! [`Sync`]: ../../std/marker/trait.Sync.html //! [`atomic`]: crate::sync::atomic #![stable(feature = "rust1", since = "1.0.0")] @@ -419,7 +462,7 @@ impl Cell { mem::replace(unsafe { &mut *self.value.get() }, val) } - /// Unwraps the value. + /// Unwraps the value, consuming the cell. /// /// # Examples /// @@ -1969,7 +2012,7 @@ impl UnsafeCell { UnsafeCell { value } } - /// Unwraps the value. + /// Unwraps the value, consuming the cell. /// /// # Examples /// @@ -2133,7 +2176,7 @@ impl SyncUnsafeCell { 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() diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index c5bd7a5fa01..5dc2d523198 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -4,8 +4,10 @@ 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. +/// This allows obtaining a shared `&T` reference to its inner value without copying or replacing +/// it (unlike [`Cell`]), and without runtime borrow checks (unlike [`RefCell`]). However, +/// only immutable references can be obtained unless one has a mutable reference to the cell +/// itself. /// /// For a thread-safe version of this struct, see [`std::sync::OnceLock`]. /// diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 5dd585b9b37..19641753ffe 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -133,7 +133,9 @@ //! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at //! most one thread at a time is able to access some data. //! -//! - [`Once`]: Used for thread-safe, one-time initialization of a +//! - [`Once`]: Used for a thread-safe, one-time global initialization routine +//! +//! - [`OnceLock`]: Used for thread-safe, one-time initialization of a //! global variable. //! //! - [`RwLock`]: Provides a mutual exclusion mechanism which allows @@ -147,6 +149,7 @@ //! [`mpsc`]: crate::sync::mpsc //! [`Mutex`]: crate::sync::Mutex //! [`Once`]: crate::sync::Once +//! [`OnceLock`]: crate::sync::OnceLock //! [`RwLock`]: crate::sync::RwLock #![stable(feature = "rust1", since = "1.0.0")] From 9b5122976e9eb0f2f0b8def82fbcd972837880e4 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 29 Mar 2023 21:25:27 +0200 Subject: [PATCH 3/3] Em dashes are cooler than hyphens. --- library/core/src/cell.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index d378b0b3b97..63bce5d0ccd 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -12,7 +12,7 @@ //! //! Shareable mutable containers exist to permit mutability in a controlled manner, even in the //! presence of aliasing. [`Cell`], [`RefCell`], and [`OnceCell`] allow doing this in -//! a single-threaded way - they do not implement [`Sync`]. (If you need to do aliasing and +//! a single-threaded way—they do not implement [`Sync`]. (If you need to do aliasing and //! mutation among multiple threads, [`Mutex`], [`RwLock`], [`OnceLock`] or [`atomic`] //! types are the correct data structures to do so). //!