about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock48
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs2
-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/jobserver.rs4
-rw-r--r--compiler/rustc_data_structures/src/sync.rs4
-rw-r--r--compiler/rustc_driver/src/lib.rs8
-rw-r--r--compiler/rustc_error_messages/src/lib.rs4
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs6
-rw-r--r--compiler/rustc_hir/src/lang_items.rs4
-rw-r--r--compiler/rustc_hir/src/weak_lang_items.rs4
-rw-r--r--compiler/rustc_interface/src/passes.rs6
-rw-r--r--compiler/rustc_interface/src/util.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/debug.rs4
-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/src/str/converts.rs5
-rw-r--r--library/core/src/str/error.rs6
-rw-r--r--library/core/tests/lazy.rs5
-rw-r--r--library/std/src/io/stdio.rs9
-rw-r--r--library/std/src/lazy.rs616
-rw-r--r--library/std/src/sync/condvar.rs4
-rw-r--r--library/std/src/sync/lazy_lock.rs121
-rw-r--r--library/std/src/sync/lazy_lock/tests.rs143
-rw-r--r--library/std/src/sync/mod.rs7
-rw-r--r--library/std/src/sync/mutex.rs4
-rw-r--r--library/std/src/sync/once_lock.rs496
-rw-r--r--library/std/src/sync/once_lock/tests.rs (renamed from library/std/src/lazy/tests.rs)165
-rw-r--r--library/std/src/sync/poison.rs1
-rw-r--r--library/std/src/sync/rwlock.rs4
-rw-r--r--library/std/src/sys/itron/mutex.rs1
-rw-r--r--library/std/src/sys/solid/rwlock.rs1
-rw-r--r--library/std/src/sys/unsupported/locks/condvar.rs1
-rw-r--r--library/std/src/sys/unsupported/locks/mutex.rs1
-rw-r--r--library/std/src/sys/unsupported/locks/rwlock.rs1
-rw-r--r--library/std/src/sys/windows/locks/condvar.rs1
-rw-r--r--library/std/src/sys/windows/locks/mutex.rs1
-rw-r--r--library/std/src/sys/windows/locks/rwlock.rs1
-rw-r--r--library/std/src/sys/windows/net.rs4
-rw-r--r--library/std/src/sys/windows/rand.rs4
-rw-r--r--library/std/src/sys_common/condvar.rs3
-rw-r--r--library/std/src/sys_common/mutex.rs4
-rw-r--r--library/std/src/sys_common/rwlock.rs4
-rw-r--r--src/bootstrap/tool.rs8
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile6
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile6
-rwxr-xr-xsrc/ci/docker/scripts/freebsd-toolchain.sh8
-rw-r--r--src/librustdoc/clean/types.rs2
-rw-r--r--src/librustdoc/core.rs6
-rw-r--r--src/librustdoc/html/render/write_shared.rs2
-rw-r--r--src/librustdoc/html/static/.eslintrc.js2
-rw-r--r--src/librustdoc/html/static/js/search.js5
-rw-r--r--src/librustdoc/lint.rs2
-rw-r--r--src/librustdoc/passes/bare_urls.rs4
-rw-r--r--src/test/run-make/libtest-thread-limit/test.rs8
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_dev/src/bless.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs4
-rw-r--r--src/tools/clippy/src/driver.rs6
-rw-r--r--src/tools/clippy/tests/compile-test.rs4
-rw-r--r--src/tools/clippy/tests/test_utils/mod.rs4
m---------src/tools/miri22
-rw-r--r--src/tools/rustc-workspace-hack/Cargo.toml2
67 files changed, 1342 insertions, 1273 deletions
diff --git a/Cargo.lock b/Cargo.lock
index acda64172b1..671f85ca3b6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -332,7 +332,7 @@ dependencies = [
  "cargo-test-macro",
  "cargo-test-support",
  "cargo-util",
- "clap 3.1.1",
+ "clap 3.2.5",
  "crates-io",
  "crossbeam-utils",
  "curl",
@@ -470,7 +470,7 @@ dependencies = [
 
 [[package]]
 name = "cargo-util"
-version = "0.1.3"
+version = "0.1.4"
 dependencies = [
  "anyhow",
  "core-foundation",
@@ -615,19 +615,19 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "3.1.1"
+version = "3.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d76c22c9b9b215eeb8d016ad3a90417bd13cb24cf8142756e6472445876cab7"
+checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7"
 dependencies = [
  "atty",
  "bitflags",
  "clap_derive",
+ "clap_lex",
  "indexmap",
- "lazy_static",
- "os_str_bytes",
+ "once_cell",
  "strsim 0.10.0",
  "termcolor",
- "textwrap 0.14.2",
+ "textwrap 0.15.0",
 ]
 
 [[package]]
@@ -636,14 +636,14 @@ version = "3.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25"
 dependencies = [
- "clap 3.1.1",
+ "clap 3.2.5",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "3.1.18"
+version = "3.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c"
+checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9"
 dependencies = [
  "heck 0.4.0",
  "proc-macro-error",
@@ -653,6 +653,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "clap_lex"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613"
+dependencies = [
+ "os_str_bytes",
+]
+
+[[package]]
 name = "clippy"
 version = "0.1.63"
 dependencies = [
@@ -684,7 +693,7 @@ name = "clippy_dev"
 version = "0.0.1"
 dependencies = [
  "aho-corasick",
- "clap 3.1.1",
+ "clap 3.2.5",
  "indoc",
  "itertools",
  "opener",
@@ -2334,7 +2343,7 @@ dependencies = [
  "ammonia",
  "anyhow",
  "chrono",
- "clap 3.1.1",
+ "clap 3.2.5",
  "clap_complete",
  "elasticlunr-rs",
  "env_logger 0.7.1",
@@ -2572,9 +2581,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.10.0"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
+checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
 
 [[package]]
 name = "opaque-debug"
@@ -2657,9 +2666,6 @@ name = "os_str_bytes"
 version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
-dependencies = [
- "memchr",
-]
 
 [[package]]
 name = "output_vt100"
@@ -3515,7 +3521,7 @@ version = "1.0.0"
 dependencies = [
  "bstr",
  "byteorder",
- "clap 3.1.1",
+ "clap 3.2.5",
  "crossbeam-utils",
  "libc",
  "libz-sys",
@@ -4696,7 +4702,7 @@ dependencies = [
  "anyhow",
  "bytecount",
  "cargo_metadata",
- "clap 3.1.1",
+ "clap 3.2.5",
  "derive-new",
  "diff",
  "dirs",
@@ -5259,9 +5265,9 @@ dependencies = [
 
 [[package]]
 name = "textwrap"
-version = "0.14.2"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
+checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
 
 [[package]]
 name = "thiserror"
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 1b01f4edbb3..a56a9100059 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -13,7 +13,7 @@ use rustc_span::Symbol;
 
 use cranelift_jit::{JITBuilder, JITModule};
 
-// FIXME use std::lazy::SyncOnceCell once it stabilizes
+// FIXME use std::sync::OnceLock once it stabilizes
 use once_cell::sync::OnceCell;
 
 use crate::{prelude::*, BackendConfig};
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/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs
index 41605afb44e..09baa3095a4 100644
--- a/compiler/rustc_data_structures/src/jobserver.rs
+++ b/compiler/rustc_data_structures/src/jobserver.rs
@@ -1,5 +1,5 @@
 pub use jobserver_crate::Client;
-use std::lazy::SyncLazy;
+use std::sync::LazyLock;
 
 // We can only call `from_env` once per process
 
@@ -18,7 +18,7 @@ use std::lazy::SyncLazy;
 // Also note that we stick this in a global because there could be
 // multiple rustc instances in this process, and the jobserver is
 // per-process.
-static GLOBAL_CLIENT: SyncLazy<Client> = SyncLazy::new(|| unsafe {
+static GLOBAL_CLIENT: LazyLock<Client> = LazyLock::new(|| unsafe {
     Client::from_env().unwrap_or_else(|| {
         let client = Client::new(32).expect("failed to create jobserver");
         // Acquire a token for the main thread which we can release later
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index f99ca53ab25..feb82cb0938 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;
@@ -258,7 +258,7 @@ cfg_if! {
         pub use parking_lot::MutexGuard as LockGuard;
         pub use parking_lot::MappedMutexGuard as MappedLockGuard;
 
-        pub use std::lazy::SyncOnceCell as OnceCell;
+        pub use std::sync::OnceLock as OnceCell;
 
         pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
 
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 8cdbb1a6704..caa92e74808 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -47,11 +47,11 @@ use std::env;
 use std::ffi::OsString;
 use std::fs;
 use std::io::{self, Read, Write};
-use std::lazy::SyncLazy;
 use std::panic::{self, catch_unwind};
 use std::path::PathBuf;
 use std::process::{self, Command, Stdio};
 use std::str;
+use std::sync::LazyLock;
 use std::time::Instant;
 
 pub mod args;
@@ -1141,8 +1141,8 @@ pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
     }
 }
 
-static DEFAULT_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
-    SyncLazy::new(|| {
+static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
+    LazyLock::new(|| {
         let hook = panic::take_hook();
         panic::set_hook(Box::new(|info| {
             // Invoke the default handler, which prints the actual panic message and optionally a backtrace
@@ -1237,7 +1237,7 @@ pub fn install_ice_hook() {
     if std::env::var("RUST_BACKTRACE").is_err() {
         std::env::set_var("RUST_BACKTRACE", "full");
     }
-    SyncLazy::force(&DEFAULT_HOOK);
+    LazyLock::force(&DEFAULT_HOOK);
 }
 
 /// This allows tools to enable rust logging without having to magically match rustc's
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index fd4b2daae9c..fefcaa898c1 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -18,9 +18,9 @@ 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;
+use std::sync::LazyLock as Lazy;
 
 #[cfg(parallel_compiler)]
 use intl_memoizer::concurrent::IntlLangMemoizer;
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index d4452a79dfb..6fcdfe44d8f 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -9,7 +9,7 @@ use crate::{Features, Stability};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_span::symbol::{sym, Symbol};
 
-use std::lazy::SyncLazy;
+use std::sync::LazyLock;
 
 type GateFn = fn(&Features) -> bool;
 
@@ -809,8 +809,8 @@ pub fn is_builtin_only_local(name: Symbol) -> bool {
     BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local)
 }
 
-pub static BUILTIN_ATTRIBUTE_MAP: SyncLazy<FxHashMap<Symbol, &BuiltinAttribute>> =
-    SyncLazy::new(|| {
+pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
+    LazyLock::new(|| {
         let mut map = FxHashMap::default();
         for attr in BUILTIN_ATTRIBUTES.iter() {
             if map.insert(attr.name, attr).is_some() {
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 9e5d7818924..b0bfac8e1f5 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -17,7 +17,7 @@ use rustc_macros::HashStable_Generic;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 
-use std::lazy::SyncLazy;
+use std::sync::LazyLock;
 
 pub enum LangItemGroup {
     Op,
@@ -134,7 +134,7 @@ macro_rules! language_item_table {
         }
 
         /// A mapping from the name of the lang item to its order and the form it must be of.
-        pub static ITEM_REFS: SyncLazy<FxHashMap<Symbol, (usize, Target)>> = SyncLazy::new(|| {
+        pub static ITEM_REFS: LazyLock<FxHashMap<Symbol, (usize, Target)>> = LazyLock::new(|| {
             let mut item_refs = FxHashMap::default();
             $( item_refs.insert($module::$name, (LangItem::$variant as usize, $target)); )*
             item_refs
diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs
index 78748209d1a..dad22725511 100644
--- a/compiler/rustc_hir/src/weak_lang_items.rs
+++ b/compiler/rustc_hir/src/weak_lang_items.rs
@@ -7,12 +7,12 @@ use rustc_ast as ast;
 use rustc_data_structures::stable_map::StableMap;
 use rustc_span::symbol::{sym, Symbol};
 
-use std::lazy::SyncLazy;
+use std::sync::LazyLock;
 
 macro_rules! weak_lang_items {
     ($($name:ident, $item:ident, $sym:ident;)*) => (
 
-pub static WEAK_ITEMS_REFS: SyncLazy<StableMap<Symbol, LangItem>> = SyncLazy::new(|| {
+pub static WEAK_ITEMS_REFS: LazyLock<StableMap<Symbol, LangItem>> = LazyLock::new(|| {
     let mut map = StableMap::default();
     $(map.insert(sym::$name, LangItem::$item);)*
     map
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 19f086b3a44..502afa493fe 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -44,11 +44,11 @@ use std::any::Any;
 use std::cell::RefCell;
 use std::ffi::OsString;
 use std::io::{self, BufWriter, Write};
-use std::lazy::SyncLazy;
 use std::marker::PhantomPinned;
 use std::path::{Path, PathBuf};
 use std::pin::Pin;
 use std::rc::Rc;
+use std::sync::LazyLock;
 use std::{env, fs, iter};
 
 pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
@@ -774,7 +774,7 @@ pub fn prepare_outputs(
     Ok(outputs)
 }
 
-pub static DEFAULT_QUERY_PROVIDERS: SyncLazy<Providers> = SyncLazy::new(|| {
+pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
     let providers = &mut Providers::default();
     providers.analysis = analysis;
     proc_macro_decls::provide(providers);
@@ -799,7 +799,7 @@ pub static DEFAULT_QUERY_PROVIDERS: SyncLazy<Providers> = SyncLazy::new(|| {
     *providers
 });
 
-pub static DEFAULT_EXTERN_QUERY_PROVIDERS: SyncLazy<ExternProviders> = SyncLazy::new(|| {
+pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock<ExternProviders> = LazyLock::new(|| {
     let mut extern_providers = ExternProviders::default();
     rustc_metadata::provide_extern(&mut extern_providers);
     rustc_codegen_ssa::provide_extern(&mut extern_providers);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 3fa8017dc93..fb9258eb4a9 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -24,12 +24,12 @@ use rustc_span::source_map::FileLoader;
 use rustc_span::symbol::{sym, Symbol};
 use std::env;
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
-use std::lazy::SyncOnceCell;
 use std::mem;
 #[cfg(not(parallel_compiler))]
 use std::panic;
 use std::path::{Path, PathBuf};
 use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::OnceLock;
 use std::thread;
 use tracing::info;
 
@@ -242,7 +242,7 @@ pub fn get_codegen_backend(
     maybe_sysroot: &Option<PathBuf>,
     backend_name: Option<&str>,
 ) -> Box<dyn CodegenBackend> {
-    static LOAD: SyncOnceCell<unsafe fn() -> Box<dyn CodegenBackend>> = SyncOnceCell::new();
+    static LOAD: OnceLock<unsafe fn() -> Box<dyn CodegenBackend>> = OnceLock::new();
 
     let load = LOAD.get_or_init(|| {
         let default_codegen_backend = option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("llvm");
@@ -265,7 +265,7 @@ pub fn get_codegen_backend(
 // loading, so we leave the code here. It is potentially useful for other tools
 // that want to invoke the rustc binary while linking to rustc as well.
 pub fn rustc_path<'a>() -> Option<&'a Path> {
-    static RUSTC_PATH: SyncOnceCell<Option<PathBuf>> = SyncOnceCell::new();
+    static RUSTC_PATH: OnceLock<Option<PathBuf>> = OnceLock::new();
 
     const BIN_PATH: &str = env!("RUSTC_INSTALL_BINDIR");
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 59a2053ec70..c94198c56a8 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -1,7 +1,7 @@
 //! A helpful diagram for debugging dataflow problems.
 
 use std::borrow::Cow;
-use std::lazy::SyncOnceCell;
+use std::sync::OnceLock;
 use std::{io, ops, str};
 
 use regex::Regex;
@@ -590,7 +590,7 @@ where
 
 macro_rules! regex {
     ($re:literal $(,)?) => {{
-        static RE: SyncOnceCell<regex::Regex> = SyncOnceCell::new();
+        static RE: OnceLock<regex::Regex> = OnceLock::new();
         RE.get_or_init(|| Regex::new($re).unwrap())
     }};
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index d31ac04274c..0f8679b0bd6 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -123,15 +123,15 @@ use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 
 use std::iter;
-use std::lazy::SyncOnceCell;
 use std::ops::Deref;
+use std::sync::OnceLock;
 
 pub const NESTED_INDENT: &str = "    ";
 
 const RUSTC_COVERAGE_DEBUG_OPTIONS: &str = "RUSTC_COVERAGE_DEBUG_OPTIONS";
 
 pub(super) fn debug_options<'a>() -> &'a DebugOptions {
-    static DEBUG_OPTIONS: SyncOnceCell<DebugOptions> = SyncOnceCell::new();
+    static DEBUG_OPTIONS: OnceLock<DebugOptions> = OnceLock::new();
 
     &DEBUG_OPTIONS.get_or_init(DebugOptions::from_env)
 }
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/src/str/converts.rs b/library/core/src/str/converts.rs
index 81b1db4ac6f..b0c55ca4f51 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -82,9 +82,10 @@ use super::Utf8Error;
 /// assert_eq!("💖", sparkle_heart);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
+#[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")]
+#[rustc_allow_const_fn_unstable(str_internals)]
 pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
-    // This should use `?` again, once it's `const`
+    // FIXME: This should use `?` again, once it's `const`
     match run_utf8_validation(v) {
         Ok(_) => {
             // SAFETY: validation succeeded.
diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs
index a127dd57eee..4e569fcc866 100644
--- a/library/core/src/str/error.rs
+++ b/library/core/src/str/error.rs
@@ -72,7 +72,7 @@ impl Utf8Error {
     /// assert_eq!(1, error.valid_up_to());
     /// ```
     #[stable(feature = "utf8_error", since = "1.5.0")]
-    #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
+    #[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")]
     #[must_use]
     #[inline]
     pub const fn valid_up_to(&self) -> usize {
@@ -95,11 +95,11 @@ impl Utf8Error {
     ///
     /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
     #[stable(feature = "utf8_error_error_len", since = "1.20.0")]
-    #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")]
+    #[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")]
     #[must_use]
     #[inline]
     pub const fn error_len(&self) -> Option<usize> {
-        // This should become `map` again, once it's `const`
+        // FIXME: This should become `map` again, once it's `const`
         match self.error_len {
             Some(len) => Some(len as usize),
             None => None,
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/io/stdio.rs b/library/std/src/io/stdio.rs
index ae16015e35a..e3b62894d0f 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -8,10 +8,9 @@ use crate::io::prelude::*;
 use crate::cell::{Cell, RefCell};
 use crate::fmt;
 use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
-use crate::lazy::SyncOnceCell;
 use crate::pin::Pin;
 use crate::sync::atomic::{AtomicBool, Ordering};
-use crate::sync::{Arc, Mutex, MutexGuard};
+use crate::sync::{Arc, Mutex, MutexGuard, OnceLock};
 use crate::sys::stdio;
 use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
 
@@ -318,7 +317,7 @@ pub struct StdinLock<'a> {
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stdin() -> Stdin {
-    static INSTANCE: SyncOnceCell<Mutex<BufReader<StdinRaw>>> = SyncOnceCell::new();
+    static INSTANCE: OnceLock<Mutex<BufReader<StdinRaw>>> = OnceLock::new();
     Stdin {
         inner: INSTANCE.get_or_init(|| {
             Mutex::new(BufReader::with_capacity(stdio::STDIN_BUF_SIZE, stdin_raw()))
@@ -552,7 +551,7 @@ pub struct StdoutLock<'a> {
     inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
 }
 
-static STDOUT: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = SyncOnceCell::new();
+static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();
 
 /// Constructs a new handle to the standard output of the current process.
 ///
@@ -837,7 +836,7 @@ pub fn stderr() -> Stderr {
     // Note that unlike `stdout()` we don't use `at_exit` here to register a
     // destructor. Stderr is not buffered , so there's no need to run a
     // destructor for flushing the buffer
-    static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<StderrRaw>>> = SyncOnceCell::new();
+    static INSTANCE: OnceLock<ReentrantMutex<RefCell<StderrRaw>>> = OnceLock::new();
 
     Stderr {
         inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs
index d7450962359..f8c06c3f9ae 100644
--- a/library/std/src/lazy.rs
+++ b/library/std/src/lazy.rs
@@ -1,617 +1 @@
 //! Lazy values and one-time initialization of static data.
-
-#[cfg(test)]
-mod tests;
-
-use crate::{
-    cell::{Cell, UnsafeCell},
-    fmt,
-    marker::PhantomData,
-    mem::MaybeUninit,
-    ops::{Deref, Drop},
-    panic::{RefUnwindSafe, UnwindSafe},
-    pin::Pin,
-    sync::Once,
-};
-
-#[doc(inline)]
-#[unstable(feature = "once_cell", issue = "74465")]
-pub use core::lazy::*;
-
-/// A synchronization primitive which can be written to only once.
-///
-/// This type is a thread-safe `OnceCell`.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(once_cell)]
-///
-/// use std::lazy::SyncOnceCell;
-///
-/// static CELL: SyncOnceCell<String> = SyncOnceCell::new();
-/// assert!(CELL.get().is_none());
-///
-/// std::thread::spawn(|| {
-///     let value: &String = CELL.get_or_init(|| {
-///         "Hello, World!".to_string()
-///     });
-///     assert_eq!(value, "Hello, World!");
-/// }).join().unwrap();
-///
-/// let value: Option<&String> = CELL.get();
-/// assert!(value.is_some());
-/// assert_eq!(value.unwrap().as_str(), "Hello, World!");
-/// ```
-#[unstable(feature = "once_cell", issue = "74465")]
-pub struct SyncOnceCell<T> {
-    once: Once,
-    // Whether or not the value is initialized is tracked by `state_and_queue`.
-    value: UnsafeCell<MaybeUninit<T>>,
-    /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
-    ///
-    /// ```compile_fail,E0597
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::SyncOnceCell;
-    ///
-    /// struct A<'a>(&'a str);
-    ///
-    /// impl<'a> Drop for A<'a> {
-    ///     fn drop(&mut self) {}
-    /// }
-    ///
-    /// let cell = SyncOnceCell::new();
-    /// {
-    ///     let s = String::new();
-    ///     let _ = cell.set(A(&s));
-    /// }
-    /// ```
-    _marker: PhantomData<T>,
-}
-
-// Why do we need `T: Send`?
-// Thread A creates a `SyncOnceCell` and shares it with
-// 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")]
-unsafe impl<T: Sync + Send> Sync for SyncOnceCell<T> {}
-#[unstable(feature = "once_cell", issue = "74465")]
-unsafe impl<T: Send> Send for SyncOnceCell<T> {}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for SyncOnceCell<T> {}
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: UnwindSafe> UnwindSafe for SyncOnceCell<T> {}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
-impl<T> const Default for SyncOnceCell<T> {
-    /// Creates a new empty cell.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::SyncOnceCell;
-    ///
-    /// fn main() {
-    ///     assert_eq!(SyncOnceCell::<()>::new(), SyncOnceCell::default());
-    /// }
-    /// ```
-    fn default() -> SyncOnceCell<T> {
-        SyncOnceCell::new()
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: fmt::Debug> fmt::Debug for SyncOnceCell<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.get() {
-            Some(v) => f.debug_tuple("Once").field(v).finish(),
-            None => f.write_str("Once(Uninit)"),
-        }
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: Clone> Clone for SyncOnceCell<T> {
-    fn clone(&self) -> SyncOnceCell<T> {
-        let cell = Self::new();
-        if let Some(value) = self.get() {
-            match cell.set(value.clone()) {
-                Ok(()) => (),
-                Err(_) => unreachable!(),
-            }
-        }
-        cell
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T> From<T> for SyncOnceCell<T> {
-    /// Create a new cell with its contents set to `value`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::SyncOnceCell;
-    ///
-    /// # fn main() -> Result<(), i32> {
-    /// let a = SyncOnceCell::from(3);
-    /// let b = SyncOnceCell::new();
-    /// b.set(3)?;
-    /// assert_eq!(a, b);
-    /// Ok(())
-    /// # }
-    /// ```
-    fn from(value: T) -> Self {
-        let cell = Self::new();
-        match cell.set(value) {
-            Ok(()) => cell,
-            Err(_) => unreachable!(),
-        }
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: PartialEq> PartialEq for SyncOnceCell<T> {
-    fn eq(&self, other: &SyncOnceCell<T>) -> bool {
-        self.get() == other.get()
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: Eq> Eq for SyncOnceCell<T> {}
-
-impl<T> SyncOnceCell<T> {
-    /// Creates a new empty cell.
-    #[unstable(feature = "once_cell", issue = "74465")]
-    #[must_use]
-    pub const fn new() -> SyncOnceCell<T> {
-        SyncOnceCell {
-            once: Once::new(),
-            value: UnsafeCell::new(MaybeUninit::uninit()),
-            _marker: PhantomData,
-        }
-    }
-
-    /// Gets the reference to the underlying value.
-    ///
-    /// Returns `None` if the cell is empty, or being initialized. This
-    /// method never blocks.
-    #[unstable(feature = "once_cell", issue = "74465")]
-    pub fn get(&self) -> Option<&T> {
-        if self.is_initialized() {
-            // Safe b/c checked is_initialized
-            Some(unsafe { self.get_unchecked() })
-        } else {
-            None
-        }
-    }
-
-    /// Gets the mutable reference to the underlying value.
-    ///
-    /// Returns `None` if the cell is empty. This method never blocks.
-    #[unstable(feature = "once_cell", issue = "74465")]
-    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
-            Some(unsafe { self.get_unchecked_mut() })
-        } else {
-            None
-        }
-    }
-
-    /// Sets the contents of this cell to `value`.
-    ///
-    /// May block if another thread is currently attempting to initialize the cell. The cell is
-    /// guaranteed to contain a value when set returns, though not necessarily the one provided.
-    ///
-    /// Returns `Ok(())` if the cell's value was set by this call.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::SyncOnceCell;
-    ///
-    /// static CELL: SyncOnceCell<i32> = SyncOnceCell::new();
-    ///
-    /// fn main() {
-    ///     assert!(CELL.get().is_none());
-    ///
-    ///     std::thread::spawn(|| {
-    ///         assert_eq!(CELL.set(92), Ok(()));
-    ///     }).join().unwrap();
-    ///
-    ///     assert_eq!(CELL.set(62), Err(62));
-    ///     assert_eq!(CELL.get(), Some(&92));
-    /// }
-    /// ```
-    #[unstable(feature = "once_cell", issue = "74465")]
-    pub fn set(&self, value: T) -> Result<(), T> {
-        let mut value = Some(value);
-        self.get_or_init(|| value.take().unwrap());
-        match value {
-            None => Ok(()),
-            Some(value) => Err(value),
-        }
-    }
-
-    /// Gets the contents of the cell, initializing it with `f` if the cell
-    /// was empty.
-    ///
-    /// Many threads may call `get_or_init` concurrently with different
-    /// initializing functions, but it is guaranteed that only one function
-    /// will be executed.
-    ///
-    /// # Panics
-    ///
-    /// If `f` panics, the panic is propagated to the caller, and the cell
-    /// remains uninitialized.
-    ///
-    /// It is an error to reentrantly initialize the cell from `f`. The
-    /// exact outcome is unspecified. Current implementation deadlocks, but
-    /// this may be changed to a panic in the future.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::SyncOnceCell;
-    ///
-    /// let cell = SyncOnceCell::new();
-    /// let value = cell.get_or_init(|| 92);
-    /// assert_eq!(value, &92);
-    /// let value = cell.get_or_init(|| unreachable!());
-    /// assert_eq!(value, &92);
-    /// ```
-    #[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`.
-    /// The exact outcome is unspecified. Current implementation
-    /// deadlocks, but this may be changed to a panic in the future.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::SyncOnceCell;
-    ///
-    /// let cell = SyncOnceCell::new();
-    /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
-    /// assert!(cell.get().is_none());
-    /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
-    ///     Ok(92)
-    /// });
-    /// assert_eq!(value, Ok(&92));
-    /// assert_eq!(cell.get(), Some(&92))
-    /// ```
-    #[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>,
-    {
-        // Fast path check
-        // NOTE: We need to perform an acquire on the state in this method
-        // in order to correctly synchronize `SyncLazy::force`. This is
-        // currently done by calling `self.get()`, which in turn calls
-        // `self.is_initialized()`, which in turn performs the acquire.
-        if let Some(value) = self.get() {
-            return Ok(value);
-        }
-        self.initialize(f)?;
-
-        debug_assert!(self.is_initialized());
-
-        // SAFETY: The inner value has been initialized
-        Ok(unsafe { self.get_unchecked() })
-    }
-
-    /// Internal-only API that gets the contents of the cell, initializing it
-    /// in two steps with `f` and `g` if the cell was empty.
-    ///
-    /// `f` is called to construct the value, which is then moved into the cell
-    /// and given as a (pinned) mutable reference to `g` to finish
-    /// initialization.
-    ///
-    /// This allows `g` to inspect an manipulate the value after it has been
-    /// moved into its final place in the cell, but before the cell is
-    /// considered initialized.
-    ///
-    /// # Panics
-    ///
-    /// If `f` or `g` panics, the panic is propagated to the caller, and the
-    /// cell remains uninitialized.
-    ///
-    /// With the current implementation, if `g` panics, the value from `f` will
-    /// not be dropped. This should probably be fixed if this is ever used for
-    /// a type where this matters.
-    ///
-    /// It is an error to reentrantly initialize the cell from `f`. The exact
-    /// outcome is unspecified. Current implementation deadlocks, but this may
-    /// be changed to a panic in the future.
-    pub(crate) fn get_or_init_pin<F, G>(self: Pin<&Self>, f: F, g: G) -> Pin<&T>
-    where
-        F: FnOnce() -> T,
-        G: FnOnce(Pin<&mut T>),
-    {
-        if let Some(value) = self.get_ref().get() {
-            // SAFETY: The inner value was already initialized, and will not be
-            // moved anymore.
-            return unsafe { Pin::new_unchecked(value) };
-        }
-
-        let slot = &self.value;
-
-        // Ignore poisoning from other threads
-        // If another thread panics, then we'll be able to run our closure
-        self.once.call_once_force(|_| {
-            let value = f();
-            // SAFETY: We use the Once (self.once) to guarantee unique access
-            // to the UnsafeCell (slot).
-            let value: &mut T = unsafe { (&mut *slot.get()).write(value) };
-            // SAFETY: The value has been written to its final place in
-            // self.value. We do not to move it anymore, which we promise here
-            // with a Pin<&mut T>.
-            g(unsafe { Pin::new_unchecked(value) });
-        });
-
-        // SAFETY: The inner value has been initialized, and will not be moved
-        // anymore.
-        unsafe { Pin::new_unchecked(self.get_ref().get_unchecked()) }
-    }
-
-    /// Consumes the `SyncOnceCell`, returning the wrapped value. Returns
-    /// `None` if the cell was empty.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::SyncOnceCell;
-    ///
-    /// let cell: SyncOnceCell<String> = SyncOnceCell::new();
-    /// assert_eq!(cell.into_inner(), None);
-    ///
-    /// let cell = SyncOnceCell::new();
-    /// cell.set("hello".to_string()).unwrap();
-    /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
-    /// ```
-    #[unstable(feature = "once_cell", issue = "74465")]
-    pub fn into_inner(mut self) -> Option<T> {
-        self.take()
-    }
-
-    /// Takes the value out of this `SyncOnceCell`, moving it back to an uninitialized state.
-    ///
-    /// Has no effect and returns `None` if the `SyncOnceCell` hasn't been initialized.
-    ///
-    /// Safety is guaranteed by requiring a mutable reference.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::SyncOnceCell;
-    ///
-    /// let mut cell: SyncOnceCell<String> = SyncOnceCell::new();
-    /// assert_eq!(cell.take(), None);
-    ///
-    /// let mut cell = SyncOnceCell::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> {
-        if self.is_initialized() {
-            self.once = Once::new();
-            // SAFETY: `self.value` is initialized and contains a valid `T`.
-            // `self.once` is reset, so `is_initialized()` will be false again
-            // which prevents the value from being read twice.
-            unsafe { Some((&mut *self.value.get()).assume_init_read()) }
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    fn is_initialized(&self) -> bool {
-        self.once.is_completed()
-    }
-
-    #[cold]
-    fn initialize<F, E>(&self, f: F) -> Result<(), E>
-    where
-        F: FnOnce() -> Result<T, E>,
-    {
-        let mut res: Result<(), E> = Ok(());
-        let slot = &self.value;
-
-        // Ignore poisoning from other threads
-        // If another thread panics, then we'll be able to run our closure
-        self.once.call_once_force(|p| {
-            match f() {
-                Ok(value) => {
-                    unsafe { (&mut *slot.get()).write(value) };
-                }
-                Err(e) => {
-                    res = Err(e);
-
-                    // Treat the underlying `Once` as poisoned since we
-                    // failed to initialize our value. Calls
-                    p.poison();
-                }
-            }
-        });
-        res
-    }
-
-    /// # Safety
-    ///
-    /// The value must be initialized
-    unsafe fn get_unchecked(&self) -> &T {
-        debug_assert!(self.is_initialized());
-        (&*self.value.get()).assume_init_ref()
-    }
-
-    /// # Safety
-    ///
-    /// The value must be initialized
-    unsafe fn get_unchecked_mut(&mut self) -> &mut T {
-        debug_assert!(self.is_initialized());
-        (&mut *self.value.get()).assume_init_mut()
-    }
-}
-
-unsafe impl<#[may_dangle] T> Drop for SyncOnceCell<T> {
-    fn drop(&mut self) {
-        if self.is_initialized() {
-            // SAFETY: The cell is initialized and being dropped, so it can't
-            // be accessed again. We also don't touch the `T` other than
-            // dropping it, which validates our usage of #[may_dangle].
-            unsafe { (&mut *self.value.get()).assume_init_drop() };
-        }
-    }
-}
-
-/// A value which is initialized on the first access.
-///
-/// This type is a thread-safe `Lazy`, and can be used in statics.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(once_cell)]
-///
-/// use std::collections::HashMap;
-///
-/// use std::lazy::SyncLazy;
-///
-/// static HASHMAP: SyncLazy<HashMap<i32, String>> = SyncLazy::new(|| {
-///     println!("initializing");
-///     let mut m = HashMap::new();
-///     m.insert(13, "Spica".to_string());
-///     m.insert(74, "Hoyten".to_string());
-///     m
-/// });
-///
-/// fn main() {
-///     println!("ready");
-///     std::thread::spawn(|| {
-///         println!("{:?}", HASHMAP.get(&13));
-///     }).join().unwrap();
-///     println!("{:?}", HASHMAP.get(&74));
-///
-///     // Prints:
-///     //   ready
-///     //   initializing
-///     //   Some("Spica")
-///     //   Some("Hoyten")
-/// }
-/// ```
-#[unstable(feature = "once_cell", issue = "74465")]
-pub struct SyncLazy<T, F = fn() -> T> {
-    cell: SyncOnceCell<T>,
-    init: Cell<Option<F>>,
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: fmt::Debug, F> fmt::Debug for SyncLazy<T, F> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Lazy").field("cell", &self.cell).finish_non_exhaustive()
-    }
-}
-
-// We never create a `&F` from a `&SyncLazy<T, F>` so it is fine
-// to not impl `Sync` for `F`
-// we do create a `&mut Option<F>` in `force`, but this is
-// properly synchronized, so it only happens once
-// so it also does not contribute to this impl.
-#[unstable(feature = "once_cell", issue = "74465")]
-unsafe impl<T, F: Send> Sync for SyncLazy<T, F> where SyncOnceCell<T>: Sync {}
-// auto-derived `Send` impl is OK.
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T, F: UnwindSafe> RefUnwindSafe for SyncLazy<T, F> where SyncOnceCell<T>: RefUnwindSafe {}
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T, F: UnwindSafe> UnwindSafe for SyncLazy<T, F> where SyncOnceCell<T>: UnwindSafe {}
-
-impl<T, F> SyncLazy<T, F> {
-    /// Creates a new lazy value with the given initializing
-    /// function.
-    #[unstable(feature = "once_cell", issue = "74465")]
-    pub const fn new(f: F) -> SyncLazy<T, F> {
-        SyncLazy { cell: SyncOnceCell::new(), init: Cell::new(Some(f)) }
-    }
-}
-
-impl<T, F: FnOnce() -> T> SyncLazy<T, F> {
-    /// Forces the evaluation of this lazy value and
-    /// returns a reference to result. This is equivalent
-    /// to the `Deref` impl, but is explicit.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(once_cell)]
-    ///
-    /// use std::lazy::SyncLazy;
-    ///
-    /// let lazy = SyncLazy::new(|| 92);
-    ///
-    /// assert_eq!(SyncLazy::force(&lazy), &92);
-    /// assert_eq!(&*lazy, &92);
-    /// ```
-    #[unstable(feature = "once_cell", issue = "74465")]
-    pub fn force(this: &SyncLazy<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 SyncLazy<T, F> {
-    type Target = T;
-    fn deref(&self) -> &T {
-        SyncLazy::force(self)
-    }
-}
-
-#[unstable(feature = "once_cell", issue = "74465")]
-impl<T: Default> Default for SyncLazy<T> {
-    /// Creates a new lazy value using `Default` as the initializing function.
-    fn default() -> SyncLazy<T> {
-        SyncLazy::new(T::default)
-    }
-}
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs
index 7ff2f330f8a..eb1e7135a6e 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/condvar.rs
@@ -122,8 +122,10 @@ impl Condvar {
     /// let condvar = Condvar::new();
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
     #[must_use]
-    pub fn new() -> Condvar {
+    #[inline]
+    pub const fn new() -> Condvar {
         Condvar { inner: sys::Condvar::new() }
     }
 
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
new file mode 100644
index 00000000000..535cc1c42fc
--- /dev/null
+++ b/library/std/src/sync/lazy_lock.rs
@@ -0,0 +1,121 @@
+use crate::cell::Cell;
+use crate::fmt;
+use crate::ops::Deref;
+use crate::panic::{RefUnwindSafe, UnwindSafe};
+use crate::sync::OnceLock;
+
+/// A value which is initialized on the first access.
+///
+/// This type is a thread-safe `Lazy`, and can be used in statics.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(once_cell)]
+///
+/// use std::collections::HashMap;
+///
+/// use std::sync::LazyLock;
+///
+/// static HASHMAP: LazyLock<HashMap<i32, String>> = LazyLock::new(|| {
+///     println!("initializing");
+///     let mut m = HashMap::new();
+///     m.insert(13, "Spica".to_string());
+///     m.insert(74, "Hoyten".to_string());
+///     m
+/// });
+///
+/// fn main() {
+///     println!("ready");
+///     std::thread::spawn(|| {
+///         println!("{:?}", HASHMAP.get(&13));
+///     }).join().unwrap();
+///     println!("{:?}", HASHMAP.get(&74));
+///
+///     // Prints:
+///     //   ready
+///     //   initializing
+///     //   Some("Spica")
+///     //   Some("Hoyten")
+/// }
+/// ```
+#[unstable(feature = "once_cell", issue = "74465")]
+pub struct LazyLock<T, F = fn() -> T> {
+    cell: OnceLock<T>,
+    init: Cell<Option<F>>,
+}
+
+impl<T, F> LazyLock<T, F> {
+    /// Creates a new lazy value with the given initializing
+    /// function.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub const fn new(f: F) -> LazyLock<T, F> {
+        LazyLock { cell: OnceLock::new(), init: Cell::new(Some(f)) }
+    }
+}
+
+impl<T, F: FnOnce() -> T> LazyLock<T, F> {
+    /// Forces the evaluation of this lazy value and
+    /// returns a reference to result. This is equivalent
+    /// to the `Deref` impl, but is explicit.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::sync::LazyLock;
+    ///
+    /// let lazy = LazyLock::new(|| 92);
+    ///
+    /// assert_eq!(LazyLock::force(&lazy), &92);
+    /// assert_eq!(&*lazy, &92);
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn force(this: &LazyLock<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 LazyLock<T, F> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        LazyLock::force(self)
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: Default> Default for LazyLock<T> {
+    /// Creates a new lazy value using `Default` as the initializing function.
+    fn default() -> LazyLock<T> {
+        LazyLock::new(T::default)
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Lazy").field("cell", &self.cell).finish_non_exhaustive()
+    }
+}
+
+// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
+// to not impl `Sync` for `F`
+// we do create a `&mut Option<F>` in `force`, but this is
+// properly synchronized, so it only happens once
+// so it also does not contribute to this impl.
+#[unstable(feature = "once_cell", issue = "74465")]
+unsafe impl<T, F: Send> Sync for LazyLock<T, F> where OnceLock<T>: Sync {}
+// auto-derived `Send` impl is OK.
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> where OnceLock<T>: RefUnwindSafe {}
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T, F: UnwindSafe> UnwindSafe for LazyLock<T, F> where OnceLock<T>: UnwindSafe {}
+
+#[cfg(test)]
+mod tests;
diff --git a/library/std/src/sync/lazy_lock/tests.rs b/library/std/src/sync/lazy_lock/tests.rs
new file mode 100644
index 00000000000..f11b66bfca5
--- /dev/null
+++ b/library/std/src/sync/lazy_lock/tests.rs
@@ -0,0 +1,143 @@
+use crate::{
+    cell::LazyCell,
+    panic,
+    sync::{
+        atomic::{AtomicUsize, Ordering::SeqCst},
+        Mutex,
+    },
+    sync::{LazyLock, OnceLock},
+    thread,
+};
+
+fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
+    thread::spawn(f).join().unwrap()
+}
+
+#[test]
+fn lazy_default() {
+    static CALLED: AtomicUsize = AtomicUsize::new(0);
+
+    struct Foo(u8);
+    impl Default for Foo {
+        fn default() -> Self {
+            CALLED.fetch_add(1, SeqCst);
+            Foo(42)
+        }
+    }
+
+    let lazy: LazyCell<Mutex<Foo>> = <_>::default();
+
+    assert_eq!(CALLED.load(SeqCst), 0);
+
+    assert_eq!(lazy.lock().unwrap().0, 42);
+    assert_eq!(CALLED.load(SeqCst), 1);
+
+    lazy.lock().unwrap().0 = 21;
+
+    assert_eq!(lazy.lock().unwrap().0, 21);
+    assert_eq!(CALLED.load(SeqCst), 1);
+}
+
+#[test]
+fn lazy_poisoning() {
+    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());
+    }
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn sync_lazy_new() {
+    static CALLED: AtomicUsize = AtomicUsize::new(0);
+    static SYNC_LAZY: LazyLock<i32> = LazyLock::new(|| {
+        CALLED.fetch_add(1, SeqCst);
+        92
+    });
+
+    assert_eq!(CALLED.load(SeqCst), 0);
+
+    spawn_and_wait(|| {
+        let y = *SYNC_LAZY - 30;
+        assert_eq!(y, 62);
+        assert_eq!(CALLED.load(SeqCst), 1);
+    });
+
+    let y = *SYNC_LAZY - 30;
+    assert_eq!(y, 62);
+    assert_eq!(CALLED.load(SeqCst), 1);
+}
+
+#[test]
+fn sync_lazy_default() {
+    static CALLED: AtomicUsize = AtomicUsize::new(0);
+
+    struct Foo(u8);
+    impl Default for Foo {
+        fn default() -> Self {
+            CALLED.fetch_add(1, SeqCst);
+            Foo(42)
+        }
+    }
+
+    let lazy: LazyLock<Mutex<Foo>> = <_>::default();
+
+    assert_eq!(CALLED.load(SeqCst), 0);
+
+    assert_eq!(lazy.lock().unwrap().0, 42);
+    assert_eq!(CALLED.load(SeqCst), 1);
+
+    lazy.lock().unwrap().0 = 21;
+
+    assert_eq!(lazy.lock().unwrap().0, 21);
+    assert_eq!(CALLED.load(SeqCst), 1);
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn static_sync_lazy() {
+    static XS: LazyLock<Vec<i32>> = LazyLock::new(|| {
+        let mut xs = Vec::new();
+        xs.push(1);
+        xs.push(2);
+        xs.push(3);
+        xs
+    });
+
+    spawn_and_wait(|| {
+        assert_eq!(&*XS, &vec![1, 2, 3]);
+    });
+
+    assert_eq!(&*XS, &vec![1, 2, 3]);
+}
+
+#[test]
+fn static_sync_lazy_via_fn() {
+    fn xs() -> &'static Vec<i32> {
+        static XS: OnceLock<Vec<i32>> = OnceLock::new();
+        XS.get_or_init(|| {
+            let mut xs = Vec::new();
+            xs.push(1);
+            xs.push(2);
+            xs.push(3);
+            xs
+        })
+    }
+    assert_eq!(xs(), &vec![1, 2, 3]);
+}
+
+#[test]
+fn sync_lazy_poisoning() {
+    let x: LazyLock<String> = LazyLock::new(|| panic!("kaboom"));
+    for _ in 0..2 {
+        let res = panic::catch_unwind(|| x.len());
+        assert!(res.is_err());
+    }
+}
+
+#[test]
+fn is_sync_send() {
+    fn assert_traits<T: Send + Sync>() {}
+    assert_traits::<LazyLock<String>>();
+}
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index 87d01daeafc..5fc18fda6a8 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -170,11 +170,18 @@ 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")]
+pub use self::lazy_lock::LazyLock;
+#[unstable(feature = "once_cell", issue = "74465")]
+pub use self::once_lock::OnceLock;
+
 pub mod mpsc;
 
 mod barrier;
 mod condvar;
+mod lazy_lock;
 mod mutex;
 mod once;
+mod once_lock;
 mod poison;
 mod rwlock;
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index 31342a89054..e0d13cd648c 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -213,7 +213,9 @@ impl<T> Mutex<T> {
     /// let mutex = Mutex::new(0);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(t: T) -> Mutex<T> {
+    #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
+    #[inline]
+    pub const fn new(t: T) -> Mutex<T> {
         Mutex {
             inner: sys::MovableMutex::new(),
             poison: poison::Flag::new(),
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
new file mode 100644
index 00000000000..813516040cd
--- /dev/null
+++ b/library/std/src/sync/once_lock.rs
@@ -0,0 +1,496 @@
+use crate::cell::UnsafeCell;
+use crate::fmt;
+use crate::marker::PhantomData;
+use crate::mem::MaybeUninit;
+use crate::panic::{RefUnwindSafe, UnwindSafe};
+use crate::pin::Pin;
+use crate::sync::Once;
+
+/// A synchronization primitive which can be written to only once.
+///
+/// This type is a thread-safe `OnceCell`.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(once_cell)]
+///
+/// use std::sync::OnceLock;
+///
+/// static CELL: OnceLock<String> = OnceLock::new();
+/// assert!(CELL.get().is_none());
+///
+/// std::thread::spawn(|| {
+///     let value: &String = CELL.get_or_init(|| {
+///         "Hello, World!".to_string()
+///     });
+///     assert_eq!(value, "Hello, World!");
+/// }).join().unwrap();
+///
+/// let value: Option<&String> = CELL.get();
+/// assert!(value.is_some());
+/// assert_eq!(value.unwrap().as_str(), "Hello, World!");
+/// ```
+#[unstable(feature = "once_cell", issue = "74465")]
+pub struct OnceLock<T> {
+    once: Once,
+    // Whether or not the value is initialized is tracked by `state_and_queue`.
+    value: UnsafeCell<MaybeUninit<T>>,
+    /// `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);
+    ///
+    /// impl<'a> Drop for A<'a> {
+    ///     fn drop(&mut self) {}
+    /// }
+    ///
+    /// let cell = OnceLock::new();
+    /// {
+    ///     let s = String::new();
+    ///     let _ = cell.set(A(&s));
+    /// }
+    /// ```
+    _marker: PhantomData<T>,
+}
+
+impl<T> OnceLock<T> {
+    /// Creates a new empty cell.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    #[must_use]
+    pub const fn new() -> OnceLock<T> {
+        OnceLock {
+            once: Once::new(),
+            value: UnsafeCell::new(MaybeUninit::uninit()),
+            _marker: PhantomData,
+        }
+    }
+
+    /// Gets the reference to the underlying value.
+    ///
+    /// Returns `None` if the cell is empty, or being initialized. This
+    /// method never blocks.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn get(&self) -> Option<&T> {
+        if self.is_initialized() {
+            // Safe b/c checked is_initialized
+            Some(unsafe { self.get_unchecked() })
+        } else {
+            None
+        }
+    }
+
+    /// Gets the mutable reference to the underlying value.
+    ///
+    /// Returns `None` if the cell is empty. This method never blocks.
+    #[unstable(feature = "once_cell", issue = "74465")]
+    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
+            Some(unsafe { self.get_unchecked_mut() })
+        } else {
+            None
+        }
+    }
+
+    /// Sets the contents of this cell to `value`.
+    ///
+    /// May block if another thread is currently attempting to initialize the cell. The cell is
+    /// guaranteed to contain a value when set returns, though not necessarily the one provided.
+    ///
+    /// Returns `Ok(())` if the cell's value was set by this call.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::sync::OnceLock;
+    ///
+    /// static CELL: OnceLock<i32> = OnceLock::new();
+    ///
+    /// fn main() {
+    ///     assert!(CELL.get().is_none());
+    ///
+    ///     std::thread::spawn(|| {
+    ///         assert_eq!(CELL.set(92), Ok(()));
+    ///     }).join().unwrap();
+    ///
+    ///     assert_eq!(CELL.set(62), Err(62));
+    ///     assert_eq!(CELL.get(), Some(&92));
+    /// }
+    /// ```
+    #[unstable(feature = "once_cell", issue = "74465")]
+    pub fn set(&self, value: T) -> Result<(), T> {
+        let mut value = Some(value);
+        self.get_or_init(|| value.take().unwrap());
+        match value {
+            None => Ok(()),
+            Some(value) => Err(value),
+        }
+    }
+
+    /// Gets the contents of the cell, initializing it with `f` if the cell
+    /// was empty.
+    ///
+    /// Many threads may call `get_or_init` concurrently with different
+    /// initializing functions, but it is guaranteed that only one function
+    /// will be executed.
+    ///
+    /// # Panics
+    ///
+    /// If `f` panics, the panic is propagated to the caller, and the cell
+    /// remains uninitialized.
+    ///
+    /// It is an error to reentrantly initialize the cell from `f`. The
+    /// exact outcome is unspecified. Current implementation deadlocks, but
+    /// this may be changed to a panic in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::sync::OnceLock;
+    ///
+    /// let cell = OnceLock::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`.
+    /// The exact outcome is unspecified. Current implementation
+    /// deadlocks, but this may be changed to a panic in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::sync::OnceLock;
+    ///
+    /// let cell = OnceLock::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>,
+    {
+        // Fast path check
+        // NOTE: We need to perform an acquire on the state in this method
+        // in order to correctly synchronize `LazyLock::force`. This is
+        // currently done by calling `self.get()`, which in turn calls
+        // `self.is_initialized()`, which in turn performs the acquire.
+        if let Some(value) = self.get() {
+            return Ok(value);
+        }
+        self.initialize(f)?;
+
+        debug_assert!(self.is_initialized());
+
+        // SAFETY: The inner value has been initialized
+        Ok(unsafe { self.get_unchecked() })
+    }
+
+    /// Internal-only API that gets the contents of the cell, initializing it
+    /// in two steps with `f` and `g` if the cell was empty.
+    ///
+    /// `f` is called to construct the value, which is then moved into the cell
+    /// and given as a (pinned) mutable reference to `g` to finish
+    /// initialization.
+    ///
+    /// This allows `g` to inspect an manipulate the value after it has been
+    /// moved into its final place in the cell, but before the cell is
+    /// considered initialized.
+    ///
+    /// # Panics
+    ///
+    /// If `f` or `g` panics, the panic is propagated to the caller, and the
+    /// cell remains uninitialized.
+    ///
+    /// With the current implementation, if `g` panics, the value from `f` will
+    /// not be dropped. This should probably be fixed if this is ever used for
+    /// a type where this matters.
+    ///
+    /// It is an error to reentrantly initialize the cell from `f`. The exact
+    /// outcome is unspecified. Current implementation deadlocks, but this may
+    /// be changed to a panic in the future.
+    pub(crate) fn get_or_init_pin<F, G>(self: Pin<&Self>, f: F, g: G) -> Pin<&T>
+    where
+        F: FnOnce() -> T,
+        G: FnOnce(Pin<&mut T>),
+    {
+        if let Some(value) = self.get_ref().get() {
+            // SAFETY: The inner value was already initialized, and will not be
+            // moved anymore.
+            return unsafe { Pin::new_unchecked(value) };
+        }
+
+        let slot = &self.value;
+
+        // Ignore poisoning from other threads
+        // If another thread panics, then we'll be able to run our closure
+        self.once.call_once_force(|_| {
+            let value = f();
+            // SAFETY: We use the Once (self.once) to guarantee unique access
+            // to the UnsafeCell (slot).
+            let value: &mut T = unsafe { (&mut *slot.get()).write(value) };
+            // SAFETY: The value has been written to its final place in
+            // self.value. We do not to move it anymore, which we promise here
+            // with a Pin<&mut T>.
+            g(unsafe { Pin::new_unchecked(value) });
+        });
+
+        // SAFETY: The inner value has been initialized, and will not be moved
+        // anymore.
+        unsafe { Pin::new_unchecked(self.get_ref().get_unchecked()) }
+    }
+
+    /// Consumes the `OnceLock`, returning the wrapped value. Returns
+    /// `None` if the cell was empty.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::sync::OnceLock;
+    ///
+    /// let cell: OnceLock<String> = OnceLock::new();
+    /// assert_eq!(cell.into_inner(), None);
+    ///
+    /// let cell = OnceLock::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(mut self) -> Option<T> {
+        self.take()
+    }
+
+    /// Takes the value out of this `OnceLock`, moving it back to an uninitialized state.
+    ///
+    /// Has no effect and returns `None` if the `OnceLock` hasn't been initialized.
+    ///
+    /// Safety is guaranteed by requiring a mutable reference.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::sync::OnceLock;
+    ///
+    /// let mut cell: OnceLock<String> = OnceLock::new();
+    /// assert_eq!(cell.take(), None);
+    ///
+    /// let mut cell = OnceLock::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> {
+        if self.is_initialized() {
+            self.once = Once::new();
+            // SAFETY: `self.value` is initialized and contains a valid `T`.
+            // `self.once` is reset, so `is_initialized()` will be false again
+            // which prevents the value from being read twice.
+            unsafe { Some((&mut *self.value.get()).assume_init_read()) }
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn is_initialized(&self) -> bool {
+        self.once.is_completed()
+    }
+
+    #[cold]
+    fn initialize<F, E>(&self, f: F) -> Result<(), E>
+    where
+        F: FnOnce() -> Result<T, E>,
+    {
+        let mut res: Result<(), E> = Ok(());
+        let slot = &self.value;
+
+        // Ignore poisoning from other threads
+        // If another thread panics, then we'll be able to run our closure
+        self.once.call_once_force(|p| {
+            match f() {
+                Ok(value) => {
+                    unsafe { (&mut *slot.get()).write(value) };
+                }
+                Err(e) => {
+                    res = Err(e);
+
+                    // Treat the underlying `Once` as poisoned since we
+                    // failed to initialize our value. Calls
+                    p.poison();
+                }
+            }
+        });
+        res
+    }
+
+    /// # Safety
+    ///
+    /// The value must be initialized
+    unsafe fn get_unchecked(&self) -> &T {
+        debug_assert!(self.is_initialized());
+        (&*self.value.get()).assume_init_ref()
+    }
+
+    /// # Safety
+    ///
+    /// The value must be initialized
+    unsafe fn get_unchecked_mut(&mut self) -> &mut T {
+        debug_assert!(self.is_initialized());
+        (&mut *self.value.get()).assume_init_mut()
+    }
+}
+
+// Why do we need `T: Send`?
+// Thread A creates a `OnceLock` and shares it with
+// 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")]
+unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
+#[unstable(feature = "once_cell", issue = "74465")]
+unsafe impl<T: Send> Send for OnceLock<T> {}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceLock<T> {}
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: UnwindSafe> UnwindSafe for OnceLock<T> {}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
+impl<T> const Default for OnceLock<T> {
+    /// Creates a new empty cell.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::sync::OnceLock;
+    ///
+    /// fn main() {
+    ///     assert_eq!(OnceLock::<()>::new(), OnceLock::default());
+    /// }
+    /// ```
+    fn default() -> OnceLock<T> {
+        OnceLock::new()
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: fmt::Debug> fmt::Debug for OnceLock<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.get() {
+            Some(v) => f.debug_tuple("Once").field(v).finish(),
+            None => f.write_str("Once(Uninit)"),
+        }
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: Clone> Clone for OnceLock<T> {
+    fn clone(&self) -> OnceLock<T> {
+        let cell = Self::new();
+        if let Some(value) = self.get() {
+            match cell.set(value.clone()) {
+                Ok(()) => (),
+                Err(_) => unreachable!(),
+            }
+        }
+        cell
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T> From<T> for OnceLock<T> {
+    /// Create a new cell with its contents set to `value`.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(once_cell)]
+    ///
+    /// use std::sync::OnceLock;
+    ///
+    /// # fn main() -> Result<(), i32> {
+    /// let a = OnceLock::from(3);
+    /// let b = OnceLock::new();
+    /// b.set(3)?;
+    /// assert_eq!(a, b);
+    /// Ok(())
+    /// # }
+    /// ```
+    fn from(value: T) -> Self {
+        let cell = Self::new();
+        match cell.set(value) {
+            Ok(()) => cell,
+            Err(_) => unreachable!(),
+        }
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: PartialEq> PartialEq for OnceLock<T> {
+    fn eq(&self, other: &OnceLock<T>) -> bool {
+        self.get() == other.get()
+    }
+}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+impl<T: Eq> Eq for OnceLock<T> {}
+
+#[unstable(feature = "once_cell", issue = "74465")]
+unsafe impl<#[may_dangle] T> Drop for OnceLock<T> {
+    fn drop(&mut self) {
+        if self.is_initialized() {
+            // SAFETY: The cell is initialized and being dropped, so it can't
+            // be accessed again. We also don't touch the `T` other than
+            // dropping it, which validates our usage of #[may_dangle].
+            unsafe { (&mut *self.value.get()).assume_init_drop() };
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/library/std/src/lazy/tests.rs b/library/std/src/sync/once_lock/tests.rs
index 83466eb0904..46695225b9f 100644
--- a/library/std/src/lazy/tests.rs
+++ b/library/std/src/sync/once_lock/tests.rs
@@ -1,48 +1,13 @@
 use crate::{
-    lazy::{Lazy, SyncLazy, SyncOnceCell},
     panic,
+    sync::OnceLock,
     sync::{
         atomic::{AtomicUsize, Ordering::SeqCst},
         mpsc::channel,
-        Mutex,
     },
     thread,
 };
 
-#[test]
-fn lazy_default() {
-    static CALLED: AtomicUsize = AtomicUsize::new(0);
-
-    struct Foo(u8);
-    impl Default for Foo {
-        fn default() -> Self {
-            CALLED.fetch_add(1, SeqCst);
-            Foo(42)
-        }
-    }
-
-    let lazy: Lazy<Mutex<Foo>> = <_>::default();
-
-    assert_eq!(CALLED.load(SeqCst), 0);
-
-    assert_eq!(lazy.lock().unwrap().0, 42);
-    assert_eq!(CALLED.load(SeqCst), 1);
-
-    lazy.lock().unwrap().0 = 21;
-
-    assert_eq!(lazy.lock().unwrap().0, 21);
-    assert_eq!(CALLED.load(SeqCst), 1);
-}
-
-#[test]
-fn lazy_poisoning() {
-    let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
-    for _ in 0..2 {
-        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len()));
-        assert!(res.is_err());
-    }
-}
-
 fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
     thread::spawn(f).join().unwrap()
 }
@@ -50,7 +15,7 @@ fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) ->
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
 fn sync_once_cell() {
-    static ONCE_CELL: SyncOnceCell<i32> = SyncOnceCell::new();
+    static ONCE_CELL: OnceLock<i32> = OnceLock::new();
 
     assert!(ONCE_CELL.get().is_none());
 
@@ -65,7 +30,7 @@ fn sync_once_cell() {
 
 #[test]
 fn sync_once_cell_get_mut() {
-    let mut c = SyncOnceCell::new();
+    let mut c = OnceLock::new();
     assert!(c.get_mut().is_none());
     c.set(90).unwrap();
     *c.get_mut().unwrap() += 2;
@@ -74,7 +39,7 @@ fn sync_once_cell_get_mut() {
 
 #[test]
 fn sync_once_cell_get_unchecked() {
-    let c = SyncOnceCell::new();
+    let c = OnceLock::new();
     c.set(92).unwrap();
     unsafe {
         assert_eq!(c.get_unchecked(), &92);
@@ -92,7 +57,7 @@ fn sync_once_cell_drop() {
         }
     }
 
-    let x = SyncOnceCell::new();
+    let x = OnceLock::new();
     spawn_and_wait(move || {
         x.get_or_init(|| Dropper);
         assert_eq!(DROP_CNT.load(SeqCst), 0);
@@ -104,13 +69,13 @@ fn sync_once_cell_drop() {
 
 #[test]
 fn sync_once_cell_drop_empty() {
-    let x = SyncOnceCell::<String>::new();
+    let x = OnceLock::<String>::new();
     drop(x);
 }
 
 #[test]
 fn clone() {
-    let s = SyncOnceCell::new();
+    let s = OnceLock::new();
     let c = s.clone();
     assert!(c.get().is_none());
 
@@ -121,7 +86,7 @@ fn clone() {
 
 #[test]
 fn get_or_try_init() {
-    let cell: SyncOnceCell<String> = SyncOnceCell::new();
+    let cell: OnceLock<String> = OnceLock::new();
     assert!(cell.get().is_none());
 
     let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() }));
@@ -137,122 +102,32 @@ fn get_or_try_init() {
 
 #[test]
 fn from_impl() {
-    assert_eq!(SyncOnceCell::from("value").get(), Some(&"value"));
-    assert_ne!(SyncOnceCell::from("foo").get(), Some(&"bar"));
+    assert_eq!(OnceLock::from("value").get(), Some(&"value"));
+    assert_ne!(OnceLock::from("foo").get(), Some(&"bar"));
 }
 
 #[test]
 fn partialeq_impl() {
-    assert!(SyncOnceCell::from("value") == SyncOnceCell::from("value"));
-    assert!(SyncOnceCell::from("foo") != SyncOnceCell::from("bar"));
+    assert!(OnceLock::from("value") == OnceLock::from("value"));
+    assert!(OnceLock::from("foo") != OnceLock::from("bar"));
 
-    assert!(SyncOnceCell::<String>::new() == SyncOnceCell::new());
-    assert!(SyncOnceCell::<String>::new() != SyncOnceCell::from("value".to_owned()));
+    assert!(OnceLock::<String>::new() == OnceLock::new());
+    assert!(OnceLock::<String>::new() != OnceLock::from("value".to_owned()));
 }
 
 #[test]
 fn into_inner() {
-    let cell: SyncOnceCell<String> = SyncOnceCell::new();
+    let cell: OnceLock<String> = OnceLock::new();
     assert_eq!(cell.into_inner(), None);
-    let cell = SyncOnceCell::new();
+    let cell = OnceLock::new();
     cell.set("hello".to_string()).unwrap();
     assert_eq!(cell.into_inner(), Some("hello".to_string()));
 }
 
 #[test]
-#[cfg_attr(target_os = "emscripten", ignore)]
-fn sync_lazy_new() {
-    static CALLED: AtomicUsize = AtomicUsize::new(0);
-    static SYNC_LAZY: SyncLazy<i32> = SyncLazy::new(|| {
-        CALLED.fetch_add(1, SeqCst);
-        92
-    });
-
-    assert_eq!(CALLED.load(SeqCst), 0);
-
-    spawn_and_wait(|| {
-        let y = *SYNC_LAZY - 30;
-        assert_eq!(y, 62);
-        assert_eq!(CALLED.load(SeqCst), 1);
-    });
-
-    let y = *SYNC_LAZY - 30;
-    assert_eq!(y, 62);
-    assert_eq!(CALLED.load(SeqCst), 1);
-}
-
-#[test]
-fn sync_lazy_default() {
-    static CALLED: AtomicUsize = AtomicUsize::new(0);
-
-    struct Foo(u8);
-    impl Default for Foo {
-        fn default() -> Self {
-            CALLED.fetch_add(1, SeqCst);
-            Foo(42)
-        }
-    }
-
-    let lazy: SyncLazy<Mutex<Foo>> = <_>::default();
-
-    assert_eq!(CALLED.load(SeqCst), 0);
-
-    assert_eq!(lazy.lock().unwrap().0, 42);
-    assert_eq!(CALLED.load(SeqCst), 1);
-
-    lazy.lock().unwrap().0 = 21;
-
-    assert_eq!(lazy.lock().unwrap().0, 21);
-    assert_eq!(CALLED.load(SeqCst), 1);
-}
-
-#[test]
-#[cfg_attr(target_os = "emscripten", ignore)]
-fn static_sync_lazy() {
-    static XS: SyncLazy<Vec<i32>> = SyncLazy::new(|| {
-        let mut xs = Vec::new();
-        xs.push(1);
-        xs.push(2);
-        xs.push(3);
-        xs
-    });
-
-    spawn_and_wait(|| {
-        assert_eq!(&*XS, &vec![1, 2, 3]);
-    });
-
-    assert_eq!(&*XS, &vec![1, 2, 3]);
-}
-
-#[test]
-fn static_sync_lazy_via_fn() {
-    fn xs() -> &'static Vec<i32> {
-        static XS: SyncOnceCell<Vec<i32>> = SyncOnceCell::new();
-        XS.get_or_init(|| {
-            let mut xs = Vec::new();
-            xs.push(1);
-            xs.push(2);
-            xs.push(3);
-            xs
-        })
-    }
-    assert_eq!(xs(), &vec![1, 2, 3]);
-}
-
-#[test]
-fn sync_lazy_poisoning() {
-    let x: SyncLazy<String> = SyncLazy::new(|| panic!("kaboom"));
-    for _ in 0..2 {
-        let res = panic::catch_unwind(|| x.len());
-        assert!(res.is_err());
-    }
-}
-
-#[test]
 fn is_sync_send() {
     fn assert_traits<T: Send + Sync>() {}
-    assert_traits::<SyncOnceCell<String>>();
-    assert_traits::<SyncLazy<String>>();
+    assert_traits::<OnceLock<String>>();
 }
 
 #[test]
@@ -261,7 +136,7 @@ fn eval_once_macro() {
         (|| -> $ty:ty {
             $($body:tt)*
         }) => {{
-            static ONCE_CELL: SyncOnceCell<$ty> = SyncOnceCell::new();
+            static ONCE_CELL: OnceLock<$ty> = OnceLock::new();
             fn init() -> $ty {
                 $($body)*
             }
@@ -285,7 +160,7 @@ fn eval_once_macro() {
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
 fn sync_once_cell_does_not_leak_partially_constructed_boxes() {
-    static ONCE_CELL: SyncOnceCell<String> = SyncOnceCell::new();
+    static ONCE_CELL: OnceLock<String> = OnceLock::new();
 
     let n_readers = 10;
     let n_writers = 3;
@@ -320,7 +195,7 @@ fn sync_once_cell_does_not_leak_partially_constructed_boxes() {
 
 #[test]
 fn dropck() {
-    let cell = SyncOnceCell::new();
+    let cell = OnceLock::new();
     {
         let s = String::new();
         cell.set(&s).unwrap();
diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs
index 9c918be3387..741312d5537 100644
--- a/library/std/src/sync/poison.rs
+++ b/library/std/src/sync/poison.rs
@@ -19,6 +19,7 @@ pub struct Flag {
 // all cases.
 
 impl Flag {
+    #[inline]
     pub const fn new() -> Flag {
         Flag { failed: AtomicBool::new(false) }
     }
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index 9517e7e1f03..1192c08cb1a 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -146,7 +146,9 @@ impl<T> RwLock<T> {
     /// let lock = RwLock::new(5);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(t: T) -> RwLock<T> {
+    #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
+    #[inline]
+    pub const fn new(t: T) -> RwLock<T> {
         RwLock {
             inner: sys::MovableRwLock::new(),
             poison: poison::Flag::new(),
diff --git a/library/std/src/sys/itron/mutex.rs b/library/std/src/sys/itron/mutex.rs
index 2ba8454ff92..715e94c3b3d 100644
--- a/library/std/src/sys/itron/mutex.rs
+++ b/library/std/src/sys/itron/mutex.rs
@@ -26,6 +26,7 @@ fn new_mtx() -> Result<abi::ID, ItronError> {
 }
 
 impl Mutex {
+    #[inline]
     pub const fn new() -> Mutex {
         Mutex { mtx: SpinIdOnceCell::new() }
     }
diff --git a/library/std/src/sys/solid/rwlock.rs b/library/std/src/sys/solid/rwlock.rs
index 433abc895f5..0a770cf03f2 100644
--- a/library/std/src/sys/solid/rwlock.rs
+++ b/library/std/src/sys/solid/rwlock.rs
@@ -23,6 +23,7 @@ fn new_rwl() -> Result<abi::ID, ItronError> {
 }
 
 impl RwLock {
+    #[inline]
     pub const fn new() -> RwLock {
         RwLock { rwl: SpinIdOnceCell::new() }
     }
diff --git a/library/std/src/sys/unsupported/locks/condvar.rs b/library/std/src/sys/unsupported/locks/condvar.rs
index f27bf2b26bd..e703fd0d269 100644
--- a/library/std/src/sys/unsupported/locks/condvar.rs
+++ b/library/std/src/sys/unsupported/locks/condvar.rs
@@ -6,6 +6,7 @@ pub struct Condvar {}
 pub type MovableCondvar = Condvar;
 
 impl Condvar {
+    #[inline]
     pub const fn new() -> Condvar {
         Condvar {}
     }
diff --git a/library/std/src/sys/unsupported/locks/mutex.rs b/library/std/src/sys/unsupported/locks/mutex.rs
index 56bad71b189..d7cb12e0cf9 100644
--- a/library/std/src/sys/unsupported/locks/mutex.rs
+++ b/library/std/src/sys/unsupported/locks/mutex.rs
@@ -11,6 +11,7 @@ unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {} // no threads on this platform
 
 impl Mutex {
+    #[inline]
     pub const fn new() -> Mutex {
         Mutex { locked: Cell::new(false) }
     }
diff --git a/library/std/src/sys/unsupported/locks/rwlock.rs b/library/std/src/sys/unsupported/locks/rwlock.rs
index bf6e2d3d080..aca5fb7152c 100644
--- a/library/std/src/sys/unsupported/locks/rwlock.rs
+++ b/library/std/src/sys/unsupported/locks/rwlock.rs
@@ -11,6 +11,7 @@ unsafe impl Send for RwLock {}
 unsafe impl Sync for RwLock {} // no threads on this platform
 
 impl RwLock {
+    #[inline]
     pub const fn new() -> RwLock {
         RwLock { mode: Cell::new(0) }
     }
diff --git a/library/std/src/sys/windows/locks/condvar.rs b/library/std/src/sys/windows/locks/condvar.rs
index 59e2c1be0f0..be9a2abbe35 100644
--- a/library/std/src/sys/windows/locks/condvar.rs
+++ b/library/std/src/sys/windows/locks/condvar.rs
@@ -14,6 +14,7 @@ unsafe impl Send for Condvar {}
 unsafe impl Sync for Condvar {}
 
 impl Condvar {
+    #[inline]
     pub const fn new() -> Condvar {
         Condvar { inner: UnsafeCell::new(c::CONDITION_VARIABLE_INIT) }
     }
diff --git a/library/std/src/sys/windows/locks/mutex.rs b/library/std/src/sys/windows/locks/mutex.rs
index 08f55844a0e..f91e8f9f59a 100644
--- a/library/std/src/sys/windows/locks/mutex.rs
+++ b/library/std/src/sys/windows/locks/mutex.rs
@@ -33,6 +33,7 @@ pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
 }
 
 impl Mutex {
+    #[inline]
     pub const fn new() -> Mutex {
         Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
     }
diff --git a/library/std/src/sys/windows/locks/rwlock.rs b/library/std/src/sys/windows/locks/rwlock.rs
index a32df85e2f6..fa5ffe5749f 100644
--- a/library/std/src/sys/windows/locks/rwlock.rs
+++ b/library/std/src/sys/windows/locks/rwlock.rs
@@ -11,6 +11,7 @@ unsafe impl Send for RwLock {}
 unsafe impl Sync for RwLock {}
 
 impl RwLock {
+    #[inline]
     pub const fn new() -> RwLock {
         RwLock { inner: UnsafeCell::new(c::SRWLOCK_INIT) }
     }
diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs
index 5de12313784..d1e72cd5443 100644
--- a/library/std/src/sys/windows/net.rs
+++ b/library/std/src/sys/windows/net.rs
@@ -2,13 +2,13 @@
 
 use crate::cmp;
 use crate::io::{self, IoSlice, IoSliceMut, Read};
-use crate::lazy::SyncOnceCell;
 use crate::mem;
 use crate::net::{Shutdown, SocketAddr};
 use crate::os::windows::io::{
     AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket,
 };
 use crate::ptr;
+use crate::sync::OnceLock;
 use crate::sys;
 use crate::sys::c;
 use crate::sys_common::net;
@@ -29,7 +29,7 @@ pub mod netc {
 
 pub struct Socket(OwnedSocket);
 
-static WSA_CLEANUP: SyncOnceCell<unsafe extern "system" fn() -> i32> = SyncOnceCell::new();
+static WSA_CLEANUP: OnceLock<unsafe extern "system" fn() -> i32> = OnceLock::new();
 
 /// Checks whether the Windows socket interface has been started already, and
 /// if not, starts it.
diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs
index 22e024d8552..57248e3651b 100644
--- a/library/std/src/sys/windows/rand.rs
+++ b/library/std/src/sys/windows/rand.rs
@@ -1,6 +1,6 @@
 use crate::io;
-use crate::lazy;
 use crate::mem;
+use crate::sync;
 use crate::sys::c;
 
 /// The kinds of HashMap RNG that may be available
@@ -28,7 +28,7 @@ fn get_hashmap_rng() -> HashMapRng {
     // Assume that if the preferred RNG is broken the first time we use it, it likely means
     // that: the DLL has failed to load, there is no point to calling it over-and-over again,
     // and we should cache the result
-    static VALUE: lazy::SyncOnceCell<HashMapRng> = lazy::SyncOnceCell::new();
+    static VALUE: sync::OnceLock<HashMapRng> = sync::OnceLock::new();
     *VALUE.get_or_init(choose_hashmap_rng)
 }
 
diff --git a/library/std/src/sys_common/condvar.rs b/library/std/src/sys_common/condvar.rs
index 1def0518e0a..f3ac1061b89 100644
--- a/library/std/src/sys_common/condvar.rs
+++ b/library/std/src/sys_common/condvar.rs
@@ -14,7 +14,8 @@ pub struct Condvar {
 
 impl Condvar {
     /// Creates a new condition variable for use.
-    pub fn new() -> Self {
+    #[inline]
+    pub const fn new() -> Self {
         Self { inner: imp::MovableCondvar::new(), check: CondvarCheck::new() }
     }
 
diff --git a/library/std/src/sys_common/mutex.rs b/library/std/src/sys_common/mutex.rs
index 36ea888d8de..81eefa1133f 100644
--- a/library/std/src/sys_common/mutex.rs
+++ b/library/std/src/sys_common/mutex.rs
@@ -15,6 +15,7 @@ unsafe impl Sync for StaticMutex {}
 
 impl StaticMutex {
     /// Creates a new mutex for use.
+    #[inline]
     pub const fn new() -> Self {
         Self(imp::Mutex::new())
     }
@@ -60,7 +61,8 @@ unsafe impl Sync for MovableMutex {}
 
 impl MovableMutex {
     /// Creates a new mutex.
-    pub fn new() -> Self {
+    #[inline]
+    pub const fn new() -> Self {
         Self(imp::MovableMutex::new())
     }
 
diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs
index abc9fd561f1..265cebfdc3e 100644
--- a/library/std/src/sys_common/rwlock.rs
+++ b/library/std/src/sys_common/rwlock.rs
@@ -10,6 +10,7 @@ pub struct StaticRwLock(imp::RwLock);
 
 impl StaticRwLock {
     /// Creates a new rwlock for use.
+    #[inline]
     pub const fn new() -> Self {
         Self(imp::RwLock::new())
     }
@@ -73,7 +74,8 @@ pub struct MovableRwLock(imp::MovableRwLock);
 
 impl MovableRwLock {
     /// Creates a new reader-writer lock for use.
-    pub fn new() -> Self {
+    #[inline]
+    pub const fn new() -> Self {
         Self(imp::MovableRwLock::new())
     }
 
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index b7abf6cc78d..905fa431d29 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -692,6 +692,7 @@ macro_rules! tool_extended {
        stable = $stable:expr,
        $(in_tree = $in_tree:expr,)?
        $(submodule = $submodule:literal,)?
+       $(tool_std = $tool_std:literal,)?
        $extra_deps:block;)+) => {
         $(
             #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -740,7 +741,7 @@ macro_rules! tool_extended {
                     compiler: $sel.compiler,
                     target: $sel.target,
                     tool: $tool_name,
-                    mode: Mode::ToolRustc,
+                    mode: if false $(|| $tool_std)? { Mode::ToolStd } else { Mode::ToolRustc },
                     path: $path,
                     extra_features: $sel.extra_features,
                     is_optional_tool: true,
@@ -774,7 +775,10 @@ tool_extended!((self, builder),
         });
         self.extra_features.push("clippy".to_owned());
     };
-    RustDemangler, rust_demangler, "src/tools/rust-demangler", "rust-demangler", stable=false, in_tree=true, {};
+    // FIXME: tool_std is not quite right, we shouldn't allow nightly features.
+    // But `builder.cargo` doesn't know how to handle ToolBootstrap in stages other than 0,
+    // and this is close enough for now.
+    RustDemangler, rust_demangler, "src/tools/rust-demangler", "rust-demangler", stable=false, in_tree=true, tool_std=true, {};
     Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, in_tree=true, {};
     RustAnalyzer, rust_analyzer, "src/tools/rust-analyzer/crates/rust-analyzer", "rust-analyzer", stable=false, submodule="rust-analyzer", {};
 );
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index a045666ca8a..6f9980dbc86 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -52,9 +52,9 @@ ENV \
     CFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \
     CXX_x86_64_fortanix_unknown_sgx=clang++-11 \
     CXXFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \
-    AR_i686_unknown_freebsd=i686-unknown-freebsd11-ar \
-    CC_i686_unknown_freebsd=i686-unknown-freebsd11-clang \
-    CXX_i686_unknown_freebsd=i686-unknown-freebsd11-clang++ \
+    AR_i686_unknown_freebsd=i686-unknown-freebsd12-ar \
+    CC_i686_unknown_freebsd=i686-unknown-freebsd12-clang \
+    CXX_i686_unknown_freebsd=i686-unknown-freebsd12-clang++ \
     CC=gcc-8 \
     CXX=g++-8
 
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
index 121dd3f455a..f9b1fa8951a 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
@@ -27,9 +27,9 @@ COPY scripts/cmake.sh /scripts/
 RUN /scripts/cmake.sh
 
 ENV \
-    AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd11-ar \
-    CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd11-clang \
-    CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd11-clang++
+    AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-ar \
+    CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-clang \
+    CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-clang++
 
 ENV HOSTS=x86_64-unknown-freebsd
 
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
index 2f7c57bcdc4..4a4cac1b723 100755
--- a/src/ci/docker/scripts/freebsd-toolchain.sh
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -5,8 +5,8 @@ set -eux
 
 arch=$1
 binutils_version=2.25.1
-freebsd_version=11.4
-triple=$arch-unknown-freebsd11
+freebsd_version=12.3
+triple=$arch-unknown-freebsd12
 sysroot=/usr/local/$triple
 
 hide_output() {
@@ -59,7 +59,7 @@ done
 
 # Originally downloaded from:
 # URL=https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
-URL=https://ci-mirrors.rust-lang.org/rustc/2020-08-09-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz
+URL=https://ci-mirrors.rust-lang.org/rustc/2022-05-06-freebsd-${freebsd_version}-${freebsd_arch}-base.txz
 curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
 
 # Clang can do cross-builds out of the box, if we give it the right
@@ -68,7 +68,7 @@ curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
 # there might be other problems.)
 #
 # The --target option is last because the cross-build of LLVM uses
-# --target without an OS version ("-freebsd" vs. "-freebsd11").  This
+# --target without an OS version ("-freebsd" vs. "-freebsd12").  This
 # makes Clang default to libstdc++ (which no longer exists), and also
 # controls other features, like GNU-style symbol table hashing and
 # anything predicated on the version number in the __FreeBSD__
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 83ab9acd300..2762d5e8502 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1,10 +1,10 @@
 use std::cell::RefCell;
 use std::default::Default;
 use std::hash::Hash;
-use std::lazy::SyncOnceCell as OnceCell;
 use std::path::PathBuf;
 use std::rc::Rc;
 use std::sync::Arc;
+use std::sync::OnceLock as OnceCell;
 use std::{cmp, fmt, iter};
 
 use arrayvec::ArrayVec;
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 53281bfde2e..51b245e36ba 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -21,9 +21,9 @@ use rustc_span::symbol::sym;
 use rustc_span::{source_map, Span, Symbol};
 
 use std::cell::RefCell;
-use std::lazy::SyncLazy;
 use std::mem;
 use std::rc::Rc;
+use std::sync::LazyLock;
 
 use crate::clean::inline::build_external_trait;
 use crate::clean::{self, ItemId, TraitWithExtraInfo};
@@ -293,8 +293,8 @@ pub(crate) fn create_config(
             providers.typeck_item_bodies = |_, _| {};
             // hack so that `used_trait_imports` won't try to call typeck
             providers.used_trait_imports = |_, _| {
-                static EMPTY_SET: SyncLazy<FxHashSet<LocalDefId>> =
-                    SyncLazy::new(FxHashSet::default);
+                static EMPTY_SET: LazyLock<FxHashSet<LocalDefId>> =
+                    LazyLock::new(FxHashSet::default);
                 &EMPTY_SET
             };
             // In case typeck does end up being called, don't ICE in case there were name resolution errors
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 8f08ff2ece3..9bddee199c7 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -3,9 +3,9 @@ use std::fmt::Write;
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io::{self, BufReader};
-use std::lazy::SyncLazy as Lazy;
 use std::path::{Component, Path, PathBuf};
 use std::rc::Rc;
+use std::sync::LazyLock as Lazy;
 
 use itertools::Itertools;
 use rustc_data_structures::flock;
diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js
index fc8b5678080..2817a8fe144 100644
--- a/src/librustdoc/html/static/.eslintrc.js
+++ b/src/librustdoc/html/static/.eslintrc.js
@@ -89,5 +89,7 @@ module.exports = {
         "no-multi-assign": "error",
         "no-return-assign": "error",
         "no-script-url": "error",
+        "no-sequences": "error",
+        "no-throw-literal": "error",
     }
 };
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index c726aeeff47..c0b274c0a3f 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -1333,10 +1333,7 @@ function initSearch(rawSearchIndex) {
             if (searchWord.indexOf(elem.pathLast) > -1 ||
                 row.normalizedName.indexOf(elem.pathLast) > -1
             ) {
-                // filter type: ... queries
-                if (!results_others[fullId] !== undefined) {
-                    index = row.normalizedName.indexOf(elem.pathLast);
-                }
+                index = row.normalizedName.indexOf(elem.pathLast);
             }
             lev = levenshtein(searchWord, elem.pathLast);
             if (lev > 0 && elem.pathLast.length > 2 && searchWord.indexOf(elem.pathLast) > -1) {
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index 08a1a868521..240aec52cff 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -3,7 +3,7 @@ use rustc_lint::LintStore;
 use rustc_lint_defs::{declare_tool_lint, Lint, LintId};
 use rustc_session::{lint, Session};
 
-use std::lazy::SyncLazy as Lazy;
+use std::sync::LazyLock as Lazy;
 
 /// This function is used to setup the lint initialization. By default, in rustdoc, everything
 /// is "allowed". Depending if we run in test mode or not, we want some of them to be at their
diff --git a/src/librustdoc/passes/bare_urls.rs b/src/librustdoc/passes/bare_urls.rs
index e9e810658ef..392e26ea6ac 100644
--- a/src/librustdoc/passes/bare_urls.rs
+++ b/src/librustdoc/passes/bare_urls.rs
@@ -9,8 +9,8 @@ use core::ops::Range;
 use pulldown_cmark::{Event, Parser, Tag};
 use regex::Regex;
 use rustc_errors::Applicability;
-use std::lazy::SyncLazy;
 use std::mem;
+use std::sync::LazyLock;
 
 pub(crate) const CHECK_BARE_URLS: Pass = Pass {
     name: "check-bare-urls",
@@ -18,7 +18,7 @@ pub(crate) const CHECK_BARE_URLS: Pass = Pass {
     description: "detects URLs that are not hyperlinks",
 };
 
-static URL_REGEX: SyncLazy<Regex> = SyncLazy::new(|| {
+static URL_REGEX: LazyLock<Regex> = LazyLock::new(|| {
     Regex::new(concat!(
         r"https?://",                          // url scheme
         r"([-a-zA-Z0-9@:%._\+~#=]{2,256}\.)+", // one or more subdomains
diff --git a/src/test/run-make/libtest-thread-limit/test.rs b/src/test/run-make/libtest-thread-limit/test.rs
index d899411a49e..26bc29216cf 100644
--- a/src/test/run-make/libtest-thread-limit/test.rs
+++ b/src/test/run-make/libtest-thread-limit/test.rs
@@ -1,8 +1,12 @@
 #![feature(once_cell)]
 
-use std::{io::ErrorKind, lazy::SyncOnceCell, thread::{self, Builder, ThreadId}};
+use std::{
+    io::ErrorKind,
+    sync::OnceLock,
+    thread::{self, Builder, ThreadId},
+};
 
-static THREAD_ID: SyncOnceCell<ThreadId> = SyncOnceCell::new();
+static THREAD_ID: OnceLock<ThreadId> = OnceLock::new();
 
 #[test]
 fn spawn_thread_would_block() {
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 4d92f07f34ba7fb7d7f207564942508f46c225d
+Subproject 8d42b0e8794ce3787c9f7d6d88b02ae80ebe8d1
diff --git a/src/tools/clippy/clippy_dev/src/bless.rs b/src/tools/clippy/clippy_dev/src/bless.rs
index 8e5c739afe0..f5c51b9474f 100644
--- a/src/tools/clippy/clippy_dev/src/bless.rs
+++ b/src/tools/clippy/clippy_dev/src/bless.rs
@@ -4,12 +4,12 @@
 use crate::cargo_clippy_path;
 use std::ffi::OsStr;
 use std::fs;
-use std::lazy::SyncLazy;
 use std::path::{Path, PathBuf};
+use std::sync::LazyLock;
 use walkdir::{DirEntry, WalkDir};
 
-static CLIPPY_BUILD_TIME: SyncLazy<Option<std::time::SystemTime>> =
-    SyncLazy::new(|| cargo_clippy_path().metadata().ok()?.modified().ok());
+static CLIPPY_BUILD_TIME: LazyLock<Option<std::time::SystemTime>> =
+    LazyLock::new(|| cargo_clippy_path().metadata().ok()?.modified().ok());
 
 /// # Panics
 ///
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 73c1bdd0e3f..5106c39b5c6 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -64,7 +64,7 @@ pub use self::hir_utils::{
 
 use std::collections::hash_map::Entry;
 use std::hash::BuildHasherDefault;
-use std::lazy::SyncOnceCell;
+use std::sync::OnceLock;
 use std::sync::{Mutex, MutexGuard};
 
 use if_chain::if_chain;
@@ -2080,7 +2080,7 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
     false
 }
 
-static TEST_ITEM_NAMES_CACHE: SyncOnceCell<Mutex<FxHashMap<LocalDefId, Vec<Symbol>>>> = SyncOnceCell::new();
+static TEST_ITEM_NAMES_CACHE: OnceLock<Mutex<FxHashMap<LocalDefId, Vec<Symbol>>>> = OnceLock::new();
 
 fn with_test_item_names<'tcx>(tcx: TyCtxt<'tcx>, module: LocalDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
     let cache = TEST_ITEM_NAMES_CACHE.get_or_init(|| Mutex::new(FxHashMap::default()));
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 7de40fe63ac..67467f89b47 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -21,11 +21,11 @@ use rustc_tools_util::VersionInfo;
 
 use std::borrow::Cow;
 use std::env;
-use std::lazy::SyncLazy;
 use std::ops::Deref;
 use std::panic;
 use std::path::{Path, PathBuf};
 use std::process::{exit, Command};
+use std::sync::LazyLock;
 
 /// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
 /// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
@@ -152,7 +152,7 @@ You can use tool lints to allow or deny lints from your code, eg.:
 
 const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new";
 
-static ICE_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> = SyncLazy::new(|| {
+static ICE_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> = LazyLock::new(|| {
     let hook = panic::take_hook();
     panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL)));
     hook
@@ -219,7 +219,7 @@ fn toolchain_path(home: Option<String>, toolchain: Option<String>) -> Option<Pat
 #[allow(clippy::too_many_lines)]
 pub fn main() {
     rustc_driver::init_rustc_env_logger();
-    SyncLazy::force(&ICE_HOOK);
+    LazyLock::force(&ICE_HOOK);
     exit(rustc_driver::catch_with_exit_code(move || {
         let mut orig_args: Vec<String> = env::args().collect();
 
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index 04c2eeff08b..061cda7e01e 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -12,8 +12,8 @@ use std::env::{self, remove_var, set_var, var_os};
 use std::ffi::{OsStr, OsString};
 use std::fs;
 use std::io;
-use std::lazy::SyncLazy;
 use std::path::{Path, PathBuf};
+use std::sync::LazyLock;
 use test_utils::IS_RUSTC_TEST_SUITE;
 
 mod test_utils;
@@ -69,7 +69,7 @@ extern crate tokio;
 /// dependencies must be added to Cargo.toml at the project root. Test
 /// dependencies that are not *directly* used by this test module require an
 /// `extern crate` declaration.
-static EXTERN_FLAGS: SyncLazy<String> = SyncLazy::new(|| {
+static EXTERN_FLAGS: LazyLock<String> = LazyLock::new(|| {
     let current_exe_depinfo = {
         let mut path = env::current_exe().unwrap();
         path.set_extension("d");
diff --git a/src/tools/clippy/tests/test_utils/mod.rs b/src/tools/clippy/tests/test_utils/mod.rs
index 8a4de3f6def..ea8c54e08b3 100644
--- a/src/tools/clippy/tests/test_utils/mod.rs
+++ b/src/tools/clippy/tests/test_utils/mod.rs
@@ -1,9 +1,9 @@
 #![allow(dead_code)] // see https://github.com/rust-lang/rust/issues/46379
 
-use std::lazy::SyncLazy;
 use std::path::PathBuf;
+use std::sync::LazyLock;
 
-pub static CARGO_CLIPPY_PATH: SyncLazy<PathBuf> = SyncLazy::new(|| {
+pub static CARGO_CLIPPY_PATH: LazyLock<PathBuf> = LazyLock::new(|| {
     let mut path = std::env::current_exe().unwrap();
     assert!(path.pop()); // deps
     path.set_file_name("cargo-clippy");
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 4c1f50bf2bef7b25613a4c42322de87ffcf8c92
+Subproject c4dd3f4ef98f8527aa652e8154ff044ca3e8845
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
index 992a2e83f63..40aa0e8f715 100644
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ b/src/tools/rustc-workspace-hack/Cargo.toml
@@ -73,7 +73,7 @@ features = [
 [dependencies]
 bstr = { version = "0.2.13", features = ["default"] }
 byteorder = { version = "1", features = ['default', 'std'] }
-clap = { version = "3.1.1", features = ["lazy_static", "derive", "clap_derive"]}
+clap = { version = "3.1.1", features = ["derive", "clap_derive"]}
 curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
 crossbeam-utils = { version = "0.8.0", features = ["nightly"] }
 libc = { version = "0.2.79", features = ["align"] }