diff --git a/Cargo.lock b/Cargo.lock index dae14521..4b490a4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3473,7 +3473,6 @@ dependencies = [ "mac_address", "memchr", "native-tls", - "once_cell", "percent-encoding", "regex", "rust_decimal", @@ -3512,7 +3511,6 @@ dependencies = [ "argon2", "axum", "dotenvy", - "once_cell", "rand", "regex", "serde", @@ -3633,7 +3631,6 @@ dependencies = [ "either", "heck 0.5.0", "hex", - "once_cell", "proc-macro2", "quote", "serde", @@ -3675,7 +3672,6 @@ dependencies = [ "log", "md-5", "memchr", - "once_cell", "percent-encoding", "rand", "rsa", @@ -3723,7 +3719,6 @@ dependencies = [ "md-5", "memchr", "num-bigint", - "once_cell", "rand", "rust_decimal", "serde", diff --git a/examples/postgres/axum-social-with-tests/Cargo.toml b/examples/postgres/axum-social-with-tests/Cargo.toml index 6cb3b73c..05257a61 100644 --- a/examples/postgres/axum-social-with-tests/Cargo.toml +++ b/examples/postgres/axum-social-with-tests/Cargo.toml @@ -24,7 +24,6 @@ validator = { version = "0.16.0", features = ["derive"] } # Auxilliary crates anyhow = "1.0.58" dotenvy = "0.15.1" -once_cell = "1.13.0" thiserror = "2.0.0" tracing = "0.1.35" diff --git a/examples/postgres/axum-social-with-tests/src/http/user.rs b/examples/postgres/axum-social-with-tests/src/http/user.rs index 55f7f05b..cf4db77c 100644 --- a/examples/postgres/axum-social-with-tests/src/http/user.rs +++ b/examples/postgres/axum-social-with-tests/src/http/user.rs @@ -1,9 +1,8 @@ use axum::http::StatusCode; use axum::{routing::post, Extension, Json, Router}; -use once_cell::sync::Lazy; use rand::Rng; use regex::Regex; -use std::time::Duration; +use std::{sync::LazyLock, time::Duration}; use serde::Deserialize; use sqlx::{PgExecutor, PgPool}; @@ -18,7 +17,7 @@ pub fn router() -> Router { Router::new().route("/v1/user", post(create_user)) } -static USERNAME_REGEX: Lazy = Lazy::new(|| Regex::new(r"^[0-9A-Za-z_]+$").unwrap()); +static USERNAME_REGEX: LazyLock = LazyLock::new(|| Regex::new(r"^[0-9A-Za-z_]+$").unwrap()); // CREATE USER diff --git a/sqlx-core/Cargo.toml b/sqlx-core/Cargo.toml index 51b82fa6..1bba2d65 100644 --- a/sqlx-core/Cargo.toml +++ b/sqlx-core/Cargo.toml @@ -67,7 +67,6 @@ futures-intrusive = "0.5.0" futures-util = { version = "0.3.19", default-features = false, features = ["alloc", "sink", "io"] } log = { version = "0.4.18", default-features = false } memchr = { version = "2.4.1", default-features = false } -once_cell = "1.9.0" percent-encoding = "2.1.0" regex = { version = "1.5.5", optional = true } serde = { version = "1.0.132", features = ["derive", "rc"], optional = true } diff --git a/sqlx-core/src/any/driver.rs b/sqlx-core/src/any/driver.rs index cf97b848..1fe5288c 100644 --- a/sqlx-core/src/any/driver.rs +++ b/sqlx-core/src/any/driver.rs @@ -5,11 +5,11 @@ use crate::connection::Connection; use crate::database::Database; use crate::Error; use futures_core::future::BoxFuture; -use once_cell::sync::OnceCell; use std::fmt::{Debug, Formatter}; +use std::sync::OnceLock; use url::Url; -static DRIVERS: OnceCell<&'static [AnyDriver]> = OnceCell::new(); +static DRIVERS: OnceLock<&'static [AnyDriver]> = OnceLock::new(); #[macro_export] macro_rules! declare_driver_with_optional_migrate { diff --git a/sqlx-macros-core/Cargo.toml b/sqlx-macros-core/Cargo.toml index d78cbe3d..e58540ae 100644 --- a/sqlx-macros-core/Cargo.toml +++ b/sqlx-macros-core/Cargo.toml @@ -60,7 +60,6 @@ dotenvy = { workspace = true } hex = { version = "0.4.3" } heck = { version = "0.5" } either = "1.6.1" -once_cell = "1.9.0" proc-macro2 = { version = "1.0.79", default-features = false } serde = { version = "1.0.132", features = ["derive"] } serde_json = { version = "1.0.73" } diff --git a/sqlx-macros-core/src/database/mod.rs b/sqlx-macros-core/src/database/mod.rs index a2d0a1fa..02486bd3 100644 --- a/sqlx-macros-core/src/database/mod.rs +++ b/sqlx-macros-core/src/database/mod.rs @@ -1,8 +1,6 @@ use std::collections::hash_map; use std::collections::HashMap; -use std::sync::Mutex; - -use once_cell::sync::Lazy; +use std::sync::{LazyLock, Mutex}; use sqlx_core::connection::Connection; use sqlx_core::database::Database; @@ -30,14 +28,14 @@ pub trait DatabaseExt: Database + TypeChecking { #[allow(dead_code)] pub struct CachingDescribeBlocking { - connections: Lazy>>, + connections: LazyLock>>, } #[allow(dead_code)] impl CachingDescribeBlocking { pub const fn new() -> Self { CachingDescribeBlocking { - connections: Lazy::new(|| Mutex::new(HashMap::new())), + connections: LazyLock::new(|| Mutex::new(HashMap::new())), } } diff --git a/sqlx-macros-core/src/lib.rs b/sqlx-macros-core/src/lib.rs index e8804f57..0bd8f38b 100644 --- a/sqlx-macros-core/src/lib.rs +++ b/sqlx-macros-core/src/lib.rs @@ -57,12 +57,13 @@ where { #[cfg(feature = "_rt-tokio")] { - use once_cell::sync::Lazy; + use std::sync::LazyLock; + use tokio::runtime::{self, Runtime}; // We need a single, persistent Tokio runtime since we're caching connections, // otherwise we'll get "IO driver has terminated" errors. - static TOKIO_RT: Lazy = Lazy::new(|| { + static TOKIO_RT: LazyLock = LazyLock::new(|| { runtime::Builder::new_current_thread() .enable_all() .build() diff --git a/sqlx-macros-core/src/query/data.rs b/sqlx-macros-core/src/query/data.rs index ddf55c8b..470f86f9 100644 --- a/sqlx-macros-core/src/query/data.rs +++ b/sqlx-macros-core/src/query/data.rs @@ -4,9 +4,8 @@ use std::fs; use std::io::Write as _; use std::marker::PhantomData; use std::path::{Path, PathBuf}; -use std::sync::Mutex; +use std::sync::{LazyLock, Mutex}; -use once_cell::sync::Lazy; use serde::{Serialize, Serializer}; use sqlx_core::database::Database; @@ -65,8 +64,8 @@ impl Serialize for SerializeDbName { } } -static OFFLINE_DATA_CACHE: Lazy>> = - Lazy::new(Default::default); +static OFFLINE_DATA_CACHE: LazyLock>> = + LazyLock::new(Default::default); /// Offline query data #[derive(Clone, serde::Deserialize)] diff --git a/sqlx-macros-core/src/query/mod.rs b/sqlx-macros-core/src/query/mod.rs index a5113741..402287df 100644 --- a/sqlx-macros-core/src/query/mod.rs +++ b/sqlx-macros-core/src/query/mod.rs @@ -1,9 +1,8 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, LazyLock, Mutex}; use std::{fs, io}; -use once_cell::sync::Lazy; use proc_macro2::TokenStream; use syn::Type; @@ -108,7 +107,7 @@ impl Metadata { } } -static METADATA: Lazy>> = Lazy::new(Default::default); +static METADATA: LazyLock>> = LazyLock::new(Default::default); // If we are in a workspace, lookup `workspace_root` since `CARGO_MANIFEST_DIR` won't // reflect the workspace dir: https://github.com/rust-lang/cargo/issues/3946 diff --git a/sqlx-mysql/Cargo.toml b/sqlx-mysql/Cargo.toml index 9bba7aa0..52717c42 100644 --- a/sqlx-mysql/Cargo.toml +++ b/sqlx-mysql/Cargo.toml @@ -62,7 +62,6 @@ hex = "0.4.3" itoa = "1.0.1" log = "0.4.18" memchr = { version = "2.4.1", default-features = false } -once_cell = "1.9.0" percent-encoding = "2.1.0" smallvec = "1.7.0" stringprep = "0.1.2" diff --git a/sqlx-mysql/src/testing/mod.rs b/sqlx-mysql/src/testing/mod.rs index 2b6d4671..72346d95 100644 --- a/sqlx-mysql/src/testing/mod.rs +++ b/sqlx-mysql/src/testing/mod.rs @@ -1,5 +1,6 @@ use std::ops::Deref; use std::str::FromStr; +use std::sync::OnceLock; use std::time::Duration; use futures_core::future::BoxFuture; @@ -9,7 +10,6 @@ use crate::executor::Executor; use crate::pool::{Pool, PoolOptions}; use crate::query::query; use crate::{MySql, MySqlConnectOptions, MySqlConnection, MySqlDatabaseError}; -use once_cell::sync::OnceCell; use sqlx_core::connection::Connection; use sqlx_core::query_builder::QueryBuilder; use sqlx_core::query_scalar::query_scalar; @@ -17,8 +17,8 @@ use std::fmt::Write; pub(crate) use sqlx_core::testing::*; -// Using a blocking `OnceCell` here because the critical sections are short. -static MASTER_POOL: OnceCell> = OnceCell::new(); +// Using a blocking `OnceLock` here because the critical sections are short. +static MASTER_POOL: OnceLock> = OnceLock::new(); impl TestSupport for MySql { fn test_context(args: &TestArgs) -> BoxFuture<'_, Result, Error>> { @@ -118,7 +118,7 @@ async fn test_context(args: &TestArgs) -> Result, Error> { .after_release(|_conn, _| Box::pin(async move { Ok(false) })) .connect_lazy_with(master_opts); - let master_pool = match MASTER_POOL.try_insert(pool) { + let master_pool = match once_lock_try_insert_polyfill(&MASTER_POOL, pool) { Ok(inserted) => inserted, Err((existing, pool)) => { // Sanity checks. @@ -200,7 +200,6 @@ async fn do_cleanup(conn: &mut MySqlConnection, db_name: &str) -> Result<(), Err Ok(()) } -/// Pre <0.8.4, test databases were stored by integer ID. async fn cleanup_old_dbs(conn: &mut MySqlConnection) -> Result<(), Error> { let res: Result, Error> = query_scalar("select db_id from _sqlx_test_databases") .fetch_all(&mut *conn) @@ -251,3 +250,12 @@ async fn cleanup_old_dbs(conn: &mut MySqlConnection) -> Result<(), Error> { Ok(()) } + +fn once_lock_try_insert_polyfill(this: &OnceLock, value: T) -> Result<&T, (&T, T)> { + let mut value = Some(value); + let res = this.get_or_init(|| value.take().unwrap()); + match value { + None => Ok(res), + Some(value) => Err((res, value)), + } +} diff --git a/sqlx-postgres/Cargo.toml b/sqlx-postgres/Cargo.toml index f9328d03..411d9438 100644 --- a/sqlx-postgres/Cargo.toml +++ b/sqlx-postgres/Cargo.toml @@ -63,7 +63,6 @@ itoa = "1.0.1" log = "0.4.18" memchr = { version = "2.4.1", default-features = false } num-bigint = { version = "0.4.3", optional = true } -once_cell = "1.9.0" smallvec = { version = "1.7.0", features = ["serde"] } stringprep = "0.1.2" thiserror = "2.0.0" diff --git a/sqlx-postgres/src/advisory_lock.rs b/sqlx-postgres/src/advisory_lock.rs index 047ede6b..996f6cb4 100644 --- a/sqlx-postgres/src/advisory_lock.rs +++ b/sqlx-postgres/src/advisory_lock.rs @@ -2,9 +2,9 @@ use crate::error::Result; use crate::Either; use crate::PgConnection; use hkdf::Hkdf; -use once_cell::sync::OnceCell; use sha2::Sha256; use std::ops::{Deref, DerefMut}; +use std::sync::OnceLock; /// A mutex-like type utilizing [Postgres advisory locks]. /// @@ -37,7 +37,7 @@ use std::ops::{Deref, DerefMut}; pub struct PgAdvisoryLock { key: PgAdvisoryLockKey, /// The query to execute to release this lock. - release_query: OnceCell, + release_query: OnceLock, } /// A key type natively used by Postgres advisory locks. @@ -163,7 +163,7 @@ impl PgAdvisoryLock { pub fn with_key(key: PgAdvisoryLockKey) -> Self { Self { key, - release_query: OnceCell::new(), + release_query: OnceLock::new(), } } diff --git a/sqlx-postgres/src/testing/mod.rs b/sqlx-postgres/src/testing/mod.rs index af20fe87..0c15dd80 100644 --- a/sqlx-postgres/src/testing/mod.rs +++ b/sqlx-postgres/src/testing/mod.rs @@ -1,11 +1,11 @@ use std::fmt::Write; use std::ops::Deref; use std::str::FromStr; +use std::sync::OnceLock; use std::time::Duration; use futures_core::future::BoxFuture; -use once_cell::sync::OnceCell; use sqlx_core::connection::Connection; use sqlx_core::query_scalar::query_scalar; @@ -17,8 +17,8 @@ use crate::{PgConnectOptions, PgConnection, Postgres}; pub(crate) use sqlx_core::testing::*; -// Using a blocking `OnceCell` here because the critical sections are short. -static MASTER_POOL: OnceCell> = OnceCell::new(); +// Using a blocking `OnceLock` here because the critical sections are short. +static MASTER_POOL: OnceLock> = OnceLock::new(); // Automatically delete any databases created before the start of the test binary. impl TestSupport for Postgres { @@ -106,7 +106,7 @@ async fn test_context(args: &TestArgs) -> Result, Error> { .after_release(|_conn, _| Box::pin(async move { Ok(false) })) .connect_lazy_with(master_opts); - let master_pool = match MASTER_POOL.try_insert(pool) { + let master_pool = match once_lock_try_insert_polyfill(&MASTER_POOL, pool) { Ok(inserted) => inserted, Err((existing, pool)) => { // Sanity checks. @@ -199,3 +199,12 @@ async fn do_cleanup(conn: &mut PgConnection, db_name: &str) -> Result<(), Error> Ok(()) } + +fn once_lock_try_insert_polyfill(this: &OnceLock, value: T) -> Result<&T, (&T, T)> { + let mut value = Some(value); + let res = this.get_or_init(|| value.take().unwrap()); + match value { + None => Ok(res), + Some(value) => Err((res, value)), + } +}