summaryrefslogtreecommitdiffstats
path: root/vendor/once_cell
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/once_cell
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/once_cell')
-rw-r--r--vendor/once_cell/.cargo-checksum.json2
-rw-r--r--vendor/once_cell/CHANGELOG.md11
-rw-r--r--vendor/once_cell/Cargo.lock101
-rw-r--r--vendor/once_cell/Cargo.toml29
-rw-r--r--vendor/once_cell/examples/bench_vs_lazy_static.rs51
-rw-r--r--vendor/once_cell/src/imp_cs.rs2
-rw-r--r--vendor/once_cell/src/imp_pl.rs4
-rw-r--r--vendor/once_cell/src/imp_std.rs20
-rw-r--r--vendor/once_cell/src/lib.rs163
-rw-r--r--vendor/once_cell/src/race.rs2
-rw-r--r--vendor/once_cell/tests/it.rs977
-rw-r--r--vendor/once_cell/tests/it/main.rs12
-rw-r--r--vendor/once_cell/tests/it/race.rs128
-rw-r--r--vendor/once_cell/tests/it/race_once_box.rs145
-rw-r--r--vendor/once_cell/tests/it/sync_lazy.rs176
-rw-r--r--vendor/once_cell/tests/it/sync_once_cell.rs309
-rw-r--r--vendor/once_cell/tests/it/unsync_lazy.rs134
-rw-r--r--vendor/once_cell/tests/it/unsync_once_cell.rs154
18 files changed, 1231 insertions, 1189 deletions
diff --git a/vendor/once_cell/.cargo-checksum.json b/vendor/once_cell/.cargo-checksum.json
index 5f6558293..4cb726782 100644
--- a/vendor/once_cell/.cargo-checksum.json
+++ b/vendor/once_cell/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"0cc0b7a536c63969dfe9a3482ad35be72368ae10bcb38522375ab1956f1d34d8","Cargo.lock":"8a37d0df9b1582a7f19959e9c7076de4e94bbf14d4a8cc993482cac1817ccd11","Cargo.toml":"0c350a2582981f0096c51368eba98e2ae554c523542322d06d58943d1883c346","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"e883909b29dc4d1c44270136fe2cfe7b2df6b416226b13928fdf9f1e15130be7","bors.toml":"ebd69f714a49dceb8fd10ebadfea6e2767be4732fdef49eddf6239151b4bc78c","examples/bench.rs":"1597a52529f75d6c5ad0b86759a775b1d723dfa810e2016317283b13594219da","examples/bench_acquire.rs":"9f4912ca262194cb55e893c33739c85c2f4868d07905b9dd3238552b6ce8a6e4","examples/bench_vs_lazy_static.rs":"d527294a2e73b53ac5faed8b316dfd1ae2a06adb31384134af21f10ce76333a5","examples/lazy_static.rs":"8bca1b264da21eceb1ccaf30477fc941bc71bedd030f1c6982ed3a7804abfb4f","examples/reentrant_init_deadlocks.rs":"ff84929de27a848e5b155549caa96db5db5f030afca975f8ba3f3da640083001","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","examples/test_synchronization.rs":"88abd5c16275bb2f2d77eaecf369d97681404a77b8edd0021f24bfd377c46be3","src/imp_cs.rs":"888fc76a1f4e55b1ece3ef748b0aa6a47be2d8d928c10f89ae6b4f12330c0e55","src/imp_pl.rs":"cd69042890c25fd3db97a4762abea4b814c961eadaf5d6ed7c7db17a6abd4c5b","src/imp_std.rs":"f13a5bfe08ac02eb0d5a0271cb5be9e8c534a81cddc3253aaca28b69bded8e65","src/lib.rs":"1458bb31d52c5c79d61077c8adb042afedab295a1744def7aa591bbbf005d1ba","src/race.rs":"eb977c7caed88774699fea6ac25afdfde0bad211c7a20c64a06dabcdc38e8a29","tests/it.rs":"41f50496463a0036c45ed138f158d221d379e50a91ca452ba8ffe8caa7a59e3a"},"package":"b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"24f417c25ccab9a49ff4b3b16b0da609517fd81b443df8e1b5f96322f997fb0b","Cargo.lock":"07dcbd89a8fb48503b73e50f44aa46cbb5ada9b2d9593cdb879226feaecc541f","Cargo.toml":"0682d1bd57d5d43262af293a755d29df111a515f00a60d70246947a37f8e7be3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"e883909b29dc4d1c44270136fe2cfe7b2df6b416226b13928fdf9f1e15130be7","bors.toml":"ebd69f714a49dceb8fd10ebadfea6e2767be4732fdef49eddf6239151b4bc78c","examples/bench.rs":"1597a52529f75d6c5ad0b86759a775b1d723dfa810e2016317283b13594219da","examples/bench_acquire.rs":"9f4912ca262194cb55e893c33739c85c2f4868d07905b9dd3238552b6ce8a6e4","examples/lazy_static.rs":"8bca1b264da21eceb1ccaf30477fc941bc71bedd030f1c6982ed3a7804abfb4f","examples/reentrant_init_deadlocks.rs":"ff84929de27a848e5b155549caa96db5db5f030afca975f8ba3f3da640083001","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","examples/test_synchronization.rs":"88abd5c16275bb2f2d77eaecf369d97681404a77b8edd0021f24bfd377c46be3","src/imp_cs.rs":"2f99fd6f993393bc98fd7b52203b1f210262cc834fb30661e0e7f66bc487d357","src/imp_pl.rs":"6a97f60a91ab44192dcaf028e987f6be0328b5d4d69216dcdaec93bc39401f68","src/imp_std.rs":"1c130f83be5c1360dfd379911f97797c1e4c730b845f465c8c2630467ca317d2","src/lib.rs":"cdb40128852d5624120aa49fa82ca573800d955f9c35144878604307c487bdce","src/race.rs":"917f1bc0ba2887644da447a6e9e38990c9a12e3c41c980be37ee916bf79d7677","tests/it/main.rs":"e6e9987e053af84b9d76052602995b1e777efb5bc06cd5f49009e6f03b18626c","tests/it/race.rs":"8dfe38563b6d0be890ab076be1fc1122d41a7c7792354cd7f60bc4454666b968","tests/it/race_once_box.rs":"1c2fe9e2988ec38d60c93c797fceb4c7a65d1b2e48a6a1e78db78ab91388e844","tests/it/sync_lazy.rs":"a36c5d66340b3d6d20aad331a499858a2125dfdfd624c5bf3b4b06a0b157c75c","tests/it/sync_once_cell.rs":"0d04beeb394eb53dd3fc0309fcfc382d56350e72b89d22356e0047d6c7bfef58","tests/it/unsync_lazy.rs":"51a1ffd411770d1e32399ec23feb5f61be362bbed34e100eb7509f8496224e1a","tests/it/unsync_once_cell.rs":"82b72936d7bd4090db25cfc543c01ef3206d6917ac56f09d17d4110a65deb30a"},"package":"dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"} \ No newline at end of file
diff --git a/vendor/once_cell/CHANGELOG.md b/vendor/once_cell/CHANGELOG.md
index bf489b25b..0cb846a4f 100644
--- a/vendor/once_cell/CHANGELOG.md
+++ b/vendor/once_cell/CHANGELOG.md
@@ -2,7 +2,16 @@
## Unreleased
--
+-
+
+## 1.18.0
+
+- `MSRV` is updated to 1.60.0 to take advantage of `dep:` syntax for cargo features,
+ removing "implementation details" from publicly visible surface.
+
+## 1.17.2
+
+- Avoid unnecessary synchronization in `Lazy::{force,deref}_mut()`, [#231](https://github.com/matklad/once_cell/pull/231).
## 1.17.1
diff --git a/vendor/once_cell/Cargo.lock b/vendor/once_cell/Cargo.lock
index 0ece6bb92..c545648c6 100644
--- a/vendor/once_cell/Cargo.lock
+++ b/vendor/once_cell/Cargo.lock
@@ -4,18 +4,18 @@ version = 3
[[package]]
name = "aho-corasick"
-version = "0.7.19"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
+checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
dependencies = [
"memchr",
]
[[package]]
name = "atomic-polyfill"
-version = "1.0.1"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d299f547288d6db8d5c3a2916f7b2f66134b15b8c1ac1c4357dd3b8752af7bb2"
+checksum = "c314e70d181aa6053b26e3f7fbf86d1dfff84f816a6175b967666b3506ef7289"
dependencies = [
"critical-section",
]
@@ -39,26 +39,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
[[package]]
-name = "crossbeam-utils"
-version = "0.8.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
-dependencies = [
- "cfg-if",
- "once_cell 1.14.0",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
name = "libc"
-version = "0.2.132"
+version = "0.2.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
[[package]]
name = "memchr"
@@ -68,27 +52,19 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "once_cell"
-version = "1.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
-
-[[package]]
-name = "once_cell"
-version = "1.17.1"
+version = "1.18.0"
dependencies = [
"atomic-polyfill",
"critical-section",
- "crossbeam-utils",
- "lazy_static",
"parking_lot_core",
"regex",
]
[[package]]
name = "parking_lot_core"
-version = "0.9.3"
+version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
+checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if",
"libc",
@@ -108,9 +84,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.6.0"
+version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
dependencies = [
"aho-corasick",
"memchr",
@@ -119,55 +95,78 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.6.27"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
[[package]]
name = "smallvec"
-version = "1.9.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "windows-sys"
-version = "0.36.1"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
+ "windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
name = "windows_aarch64_msvc"
-version = "0.36.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_i686_gnu"
-version = "0.36.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_msvc"
-version = "0.36.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.36.1"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.36.1"
+version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
diff --git a/vendor/once_cell/Cargo.toml b/vendor/once_cell/Cargo.toml
index 76a629114..b3a6ba60b 100644
--- a/vendor/once_cell/Cargo.toml
+++ b/vendor/once_cell/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.56"
+rust-version = "1.60"
name = "once_cell"
-version = "1.17.1"
+version = "1.18.0"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
exclude = [
"*.png",
@@ -47,10 +47,6 @@ name = "bench_acquire"
required-features = ["std"]
[[example]]
-name = "bench_vs_lazy_static"
-required-features = ["std"]
-
-[[example]]
name = "lazy_static"
required-features = ["std"]
@@ -66,31 +62,22 @@ required-features = ["std"]
name = "test_synchronization"
required-features = ["std"]
-[dependencies.atomic_polyfill]
+[dependencies.atomic-polyfill]
version = "1"
optional = true
-package = "atomic-polyfill"
-[dependencies.critical_section]
+[dependencies.critical-section]
version = "1"
optional = true
-package = "critical-section"
[dependencies.parking_lot_core]
version = "0.9.3"
optional = true
default_features = false
-[dev-dependencies.critical_section]
+[dev-dependencies.critical-section]
version = "1.1.1"
features = ["std"]
-package = "critical-section"
-
-[dev-dependencies.crossbeam-utils]
-version = "0.8.7"
-
-[dev-dependencies.lazy_static]
-version = "1.0.0"
[dev-dependencies.regex]
version = "1.2.0"
@@ -99,11 +86,11 @@ version = "1.2.0"
alloc = ["race"]
atomic-polyfill = ["critical-section"]
critical-section = [
- "critical_section",
- "atomic_polyfill",
+ "dep:critical-section",
+ "dep:atomic-polyfill",
]
default = ["std"]
-parking_lot = ["parking_lot_core"]
+parking_lot = ["dep:parking_lot_core"]
race = []
std = ["alloc"]
unstable = []
diff --git a/vendor/once_cell/examples/bench_vs_lazy_static.rs b/vendor/once_cell/examples/bench_vs_lazy_static.rs
deleted file mode 100644
index c23b0124e..000000000
--- a/vendor/once_cell/examples/bench_vs_lazy_static.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-use lazy_static::lazy_static;
-use once_cell::sync::Lazy;
-
-const N_THREADS: usize = 32;
-const N_ROUNDS: usize = 100_000_000;
-
-static ONCE_CELL: Lazy<Vec<String>> = Lazy::new(|| vec!["Spica".to_string(), "Hoyten".to_string()]);
-
-lazy_static! {
- static ref LAZY_STATIC: Vec<String> = vec!["Spica".to_string(), "Hoyten".to_string()];
-}
-
-fn main() {
- let once_cell = {
- let start = std::time::Instant::now();
- let threads = (0..N_THREADS)
- .map(|_| std::thread::spawn(move || thread_once_cell()))
- .collect::<Vec<_>>();
- for thread in threads {
- thread.join().unwrap();
- }
- start.elapsed()
- };
- let lazy_static = {
- let start = std::time::Instant::now();
- let threads = (0..N_THREADS)
- .map(|_| std::thread::spawn(move || thread_lazy_static()))
- .collect::<Vec<_>>();
- for thread in threads {
- thread.join().unwrap();
- }
- start.elapsed()
- };
-
- println!("once_cell: {:?}", once_cell);
- println!("lazy_static: {:?}", lazy_static);
-}
-
-fn thread_once_cell() {
- for _ in 0..N_ROUNDS {
- let len = ONCE_CELL.len();
- assert_eq!(len, 2)
- }
-}
-
-fn thread_lazy_static() {
- for _ in 0..N_ROUNDS {
- let len = LAZY_STATIC.len();
- assert_eq!(len, 2)
- }
-}
diff --git a/vendor/once_cell/src/imp_cs.rs b/vendor/once_cell/src/imp_cs.rs
index 668f18ec6..04018f119 100644
--- a/vendor/once_cell/src/imp_cs.rs
+++ b/vendor/once_cell/src/imp_cs.rs
@@ -63,7 +63,7 @@ impl<T> OnceCell<T> {
pub(crate) unsafe fn get_unchecked(&self) -> &T {
debug_assert!(self.is_initialized());
// SAFETY: The caller ensures that the value is initialized and access synchronized.
- crate::unwrap_unchecked(self.value.borrow(CriticalSection::new()).get())
+ self.value.borrow(CriticalSection::new()).get().unwrap_unchecked()
}
#[inline]
diff --git a/vendor/once_cell/src/imp_pl.rs b/vendor/once_cell/src/imp_pl.rs
index 84d859386..37a85547d 100644
--- a/vendor/once_cell/src/imp_pl.rs
+++ b/vendor/once_cell/src/imp_pl.rs
@@ -58,7 +58,7 @@ impl<T> OnceCell<T> {
// but that is more complicated
// - finally, if it returns Ok, we store the value and store the flag with
// `Release`, which synchronizes with `Acquire`s.
- let f = unsafe { crate::unwrap_unchecked(f.take()) };
+ let f = unsafe { f.take().unwrap_unchecked() };
match f() {
Ok(value) => unsafe {
// Safe b/c we have a unique access and no panic may happen
@@ -101,7 +101,7 @@ impl<T> OnceCell<T> {
pub(crate) unsafe fn get_unchecked(&self) -> &T {
debug_assert!(self.is_initialized());
let slot = &*self.value.get();
- crate::unwrap_unchecked(slot.as_ref())
+ slot.as_ref().unwrap_unchecked()
}
/// Gets the mutable reference to the underlying value.
diff --git a/vendor/once_cell/src/imp_std.rs b/vendor/once_cell/src/imp_std.rs
index 5761f0184..3b9e6d205 100644
--- a/vendor/once_cell/src/imp_std.rs
+++ b/vendor/once_cell/src/imp_std.rs
@@ -5,7 +5,6 @@
use std::{
cell::{Cell, UnsafeCell},
- marker::PhantomData,
panic::{RefUnwindSafe, UnwindSafe},
sync::atomic::{AtomicBool, AtomicPtr, Ordering},
thread::{self, Thread},
@@ -22,7 +21,6 @@ pub(crate) struct OnceCell<T> {
// State is encoded in two low bits. Only `INCOMPLETE` and `RUNNING` states
// allow waiters.
queue: AtomicPtr<Waiter>,
- _marker: PhantomData<*mut Waiter>,
value: UnsafeCell<Option<T>>,
}
@@ -39,19 +37,11 @@ impl<T: UnwindSafe> UnwindSafe for OnceCell<T> {}
impl<T> OnceCell<T> {
pub(crate) const fn new() -> OnceCell<T> {
- OnceCell {
- queue: AtomicPtr::new(INCOMPLETE_PTR),
- _marker: PhantomData,
- value: UnsafeCell::new(None),
- }
+ OnceCell { queue: AtomicPtr::new(INCOMPLETE_PTR), value: UnsafeCell::new(None) }
}
pub(crate) const fn with_value(value: T) -> OnceCell<T> {
- OnceCell {
- queue: AtomicPtr::new(COMPLETE_PTR),
- _marker: PhantomData,
- value: UnsafeCell::new(Some(value)),
- }
+ OnceCell { queue: AtomicPtr::new(COMPLETE_PTR), value: UnsafeCell::new(Some(value)) }
}
/// Safety: synchronizes with store to value via Release/(Acquire|SeqCst).
@@ -78,7 +68,7 @@ impl<T> OnceCell<T> {
initialize_or_wait(
&self.queue,
Some(&mut || {
- let f = unsafe { crate::unwrap_unchecked(f.take()) };
+ let f = unsafe { f.take().unwrap_unchecked() };
match f() {
Ok(value) => {
unsafe { *slot = Some(value) };
@@ -109,7 +99,7 @@ impl<T> OnceCell<T> {
pub(crate) unsafe fn get_unchecked(&self) -> &T {
debug_assert!(self.is_initialized());
let slot = &*self.value.get();
- crate::unwrap_unchecked(slot.as_ref())
+ slot.as_ref().unwrap_unchecked()
}
/// Gets the mutable reference to the underlying value.
@@ -209,7 +199,7 @@ fn initialize_or_wait(queue: &AtomicPtr<Waiter>, mut init: Option<&mut dyn FnMut
return;
}
(INCOMPLETE, None) | (RUNNING, _) => {
- wait(&queue, curr_queue);
+ wait(queue, curr_queue);
curr_queue = queue.load(Ordering::Acquire);
}
_ => debug_assert!(false),
diff --git a/vendor/once_cell/src/lib.rs b/vendor/once_cell/src/lib.rs
index c2061f89f..db7e19a8a 100644
--- a/vendor/once_cell/src/lib.rs
+++ b/vendor/once_cell/src/lib.rs
@@ -1,8 +1,10 @@
//! # Overview
//!
-//! `once_cell` provides two new cell-like types, [`unsync::OnceCell`] and [`sync::OnceCell`]. A `OnceCell`
-//! might store arbitrary non-`Copy` types, can be assigned to at most once and provides direct access
-//! to the stored contents. The core API looks *roughly* like this (and there's much more inside, read on!):
+//! `once_cell` provides two new cell-like types, [`unsync::OnceCell`] and
+//! [`sync::OnceCell`]. A `OnceCell` might store arbitrary non-`Copy` types, can
+//! be assigned to at most once and provides direct access to the stored
+//! contents. The core API looks *roughly* like this (and there's much more
+//! inside, read on!):
//!
//! ```rust,ignore
//! impl<T> OnceCell<T> {
@@ -12,11 +14,12 @@
//! }
//! ```
//!
-//! Note that, like with [`RefCell`] and [`Mutex`], the `set` method requires only a shared reference.
-//! Because of the single assignment restriction `get` can return a `&T` instead of `Ref<T>`
-//! or `MutexGuard<T>`.
+//! Note that, like with [`RefCell`] and [`Mutex`], the `set` method requires
+//! only a shared reference. Because of the single assignment restriction `get`
+//! can return a `&T` instead of `Ref<T>` or `MutexGuard<T>`.
//!
-//! The `sync` flavor is thread-safe (that is, implements the [`Sync`] trait), while the `unsync` one is not.
+//! The `sync` flavor is thread-safe (that is, implements the [`Sync`] trait),
+//! while the `unsync` one is not.
//!
//! [`unsync::OnceCell`]: unsync/struct.OnceCell.html
//! [`sync::OnceCell`]: sync/struct.OnceCell.html
@@ -79,7 +82,8 @@
//! }
//! ```
//!
-//! There are also the [`sync::Lazy`] and [`unsync::Lazy`] convenience types to streamline this pattern:
+//! There are also the [`sync::Lazy`] and [`unsync::Lazy`] convenience types to
+//! streamline this pattern:
//!
//! ```rust
//! use std::{sync::Mutex, collections::HashMap};
@@ -120,7 +124,8 @@
//! ```
//!
//! If you need a lazy field in a struct, you probably should use `OnceCell`
-//! directly, because that will allow you to access `self` during initialization.
+//! directly, because that will allow you to access `self` during
+//! initialization.
//!
//! ```rust
//! use std::{fs, path::PathBuf};
@@ -156,7 +161,8 @@
//! }
//! ```
//!
-//! This macro can be useful to avoid the "compile regex on every loop iteration" problem.
+//! This macro can be useful to avoid the "compile regex on every loop
+//! iteration" problem.
//!
//! ## Runtime `include_bytes!`
//!
@@ -243,7 +249,7 @@
//! let b = B::default();
//! a.b.init(&b);
//! b.a.init(&a);
-//!
+//!
//! let _a = &a.b.a.b.a;
//! }
//! ```
@@ -262,23 +268,28 @@
//! |`Mutex<T>` | `MutexGuard<T>` | may deadlock at runtime, may block the thread |
//! |`sync::OnceCell<T>` | `&T` | assignable only once, may block the thread |
//!
-//! Technically, calling `get_or_init` will also cause a panic or a deadlock if it recursively calls
-//! itself. However, because the assignment can happen only once, such cases should be more rare than
-//! equivalents with `RefCell` and `Mutex`.
+//! Technically, calling `get_or_init` will also cause a panic or a deadlock if
+//! it recursively calls itself. However, because the assignment can happen only
+//! once, such cases should be more rare than equivalents with `RefCell` and
+//! `Mutex`.
//!
//! # Minimum Supported `rustc` Version
//!
//! This crate's minimum supported `rustc` version is `1.56.0`.
//!
-//! If only the `std` feature is enabled, MSRV will be updated conservatively, supporting at least latest 8 versions of the compiler.
-//! When using other features, like `parking_lot`, MSRV might be updated more frequently, up to the latest stable.
-//! In both cases, increasing MSRV is *not* considered a semver-breaking change.
+//! If only the `std` feature is enabled, MSRV will be updated conservatively,
+//! supporting at least latest 8 versions of the compiler. When using other
+//! features, like `parking_lot`, MSRV might be updated more frequently, up to
+//! the latest stable. In both cases, increasing MSRV is *not* considered a
+//! semver-breaking change.
//!
//! # Implementation details
//!
-//! The implementation is based on the [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/)
-//! and [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and [`std::sync::Once`]. In some sense,
-//! `once_cell` just streamlines and unifies those APIs.
+//! The implementation is based on the
+//! [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/) and
+//! [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and
+//! [`std::sync::Once`]. In some sense, `once_cell` just streamlines and unifies
+//! those APIs.
//!
//! To implement a sync flavor of `OnceCell`, this crates uses either a custom
//! re-implementation of `std::sync::Once` or `parking_lot::Mutex`. This is
@@ -292,46 +303,66 @@
//!
//! # F.A.Q.
//!
-//! **Should I use lazy_static or once_cell?**
+//! **Should I use the sync or unsync flavor?**
//!
-//! To the first approximation, `once_cell` is both more flexible and more convenient than `lazy_static`
-//! and should be preferred.
+//! Because Rust compiler checks thread safety for you, it's impossible to
+//! accidentally use `unsync` where `sync` is required. So, use `unsync` in
+//! single-threaded code and `sync` in multi-threaded. It's easy to switch
+//! between the two if code becomes multi-threaded later.
//!
-//! Unlike `once_cell`, `lazy_static` supports spinlock-based implementation of blocking which works with
-//! `#![no_std]`.
+//! At the moment, `unsync` has an additional benefit that reentrant
+//! initialization causes a panic, which might be easier to debug than a
+//! deadlock.
//!
-//! `lazy_static` has received significantly more real world testing, but `once_cell` is also a widely
-//! used crate.
+//! **Does this crate support async?**
//!
-//! **Should I use the sync or unsync flavor?**
+//! No, but you can use
+//! [`async_once_cell`](https://crates.io/crates/async_once_cell) instead.
//!
-//! Because Rust compiler checks thread safety for you, it's impossible to accidentally use `unsync` where
-//! `sync` is required. So, use `unsync` in single-threaded code and `sync` in multi-threaded. It's easy
-//! to switch between the two if code becomes multi-threaded later.
+//! **Does this crate support `no_std`?**
//!
-//! At the moment, `unsync` has an additional benefit that reentrant initialization causes a panic, which
-//! might be easier to debug than a deadlock.
+//! Yes, but with caveats. `OnceCell` is a synchronization primitive which
+//! _semantically_ relies on blocking. `OnceCell` guarantees that at most one
+//! `f` will be called to compute the value. If two threads of execution call
+//! `get_or_init` concurrently, one of them has to wait.
//!
-//! **Does this crate support async?**
+//! Waiting fundamentally requires OS support. Execution environment needs to
+//! understand who waits on whom to prevent deadlocks due to priority inversion.
+//! You _could_ make code to compile by blindly using pure spinlocks, but the
+//! runtime behavior would be subtly wrong.
+//!
+//! Given these constraints, `once_cell` provides the following options:
//!
-//! No, but you can use [`async_once_cell`](https://crates.io/crates/async_once_cell) instead.
+//! - The `race` module provides similar, but distinct synchronization primitive
+//! which is compatible with `no_std`. With `race`, the `f` function can be
+//! called multiple times by different threads, but only one thread will win
+//! to install the value.
+//! - `critical-section` feature (with a `-`, not `_`) uses `critical_section`
+//! to implement blocking.
//!
//! **Can I bring my own mutex?**
//!
-//! There is [generic_once_cell](https://crates.io/crates/generic_once_cell) to allow just that.
+//! There is [generic_once_cell](https://crates.io/crates/generic_once_cell) to
+//! allow just that.
+//!
+//! **Should I use `std::cell::OnceCell`, `once_cell`, or `lazy_static`?**
+//!
+//! If you can use `std` version (your MSRV is at least 1.70, and you don't need
+//! extra features `once_cell` provides), use `std`. Otherwise, use `once_cell`.
+//! Don't use `lazy_static`.
//!
//! # Related crates
//!
+//! * Most of this crate's functionality is available in `std` starting with
+//! Rust 1.70. See `std::cell::OnceCell` and `std::sync::OnceLock`.
//! * [double-checked-cell](https://github.com/niklasf/double-checked-cell)
//! * [lazy-init](https://crates.io/crates/lazy-init)
//! * [lazycell](https://crates.io/crates/lazycell)
//! * [mitochondria](https://crates.io/crates/mitochondria)
//! * [lazy_static](https://crates.io/crates/lazy_static)
//! * [async_once_cell](https://crates.io/crates/async_once_cell)
-//! * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring your own mutex)
-//!
-//! Most of this crate's functionality is available in `std` in nightly Rust.
-//! See the [tracking issue](https://github.com/rust-lang/rust/issues/74465).
+//! * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring
+//! your own mutex)
#![cfg_attr(not(feature = "std"), no_std)]
@@ -359,8 +390,6 @@ pub mod unsync {
panic::{RefUnwindSafe, UnwindSafe},
};
- use super::unwrap_unchecked;
-
/// A cell which can be written to only once. It is not thread safe.
///
/// Unlike [`std::cell::RefCell`], a `OnceCell` provides simple `&`
@@ -532,7 +561,7 @@ pub mod unsync {
// checked that slot is currently `None`, so this write
// maintains the `inner`'s invariant.
*slot = Some(value);
- Ok(unsafe { unwrap_unchecked(slot.as_ref()) })
+ Ok(unsafe { slot.as_ref().unwrap_unchecked() })
}
/// Gets the contents of the cell, initializing it with `f`
@@ -605,7 +634,7 @@ pub mod unsync {
// `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(unsafe { unwrap_unchecked(self.get()) })
+ Ok(unsafe { self.get().unwrap_unchecked() })
}
/// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
@@ -638,7 +667,7 @@ pub mod unsync {
/// cell = OnceCell::new();
/// ```
pub fn take(&mut self) -> Option<T> {
- mem::replace(self, Self::default()).into_inner()
+ mem::take(self).into_inner()
}
/// Consumes the `OnceCell`, returning the wrapped value.
@@ -765,8 +794,14 @@ pub mod unsync {
/// assert_eq!(*lazy, 92);
/// ```
pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T {
- Self::force(this);
- Self::get_mut(this).unwrap_or_else(|| unreachable!())
+ if this.cell.get_mut().is_none() {
+ let value = match this.init.get_mut().take() {
+ Some(f) => f(),
+ None => panic!("Lazy instance has previously been poisoned"),
+ };
+ this.cell = OnceCell::with_value(value);
+ }
+ this.cell.get_mut().unwrap_or_else(|| unreachable!())
}
/// Gets the reference to the result of this lazy value if
@@ -813,8 +848,7 @@ pub mod unsync {
impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> {
fn deref_mut(&mut self) -> &mut T {
- Lazy::force(self);
- self.cell.get_mut().unwrap_or_else(|| unreachable!())
+ Lazy::force_mut(self)
}
}
@@ -836,7 +870,7 @@ pub mod sync {
panic::RefUnwindSafe,
};
- use super::{imp::OnceCell as Imp, unwrap_unchecked};
+ use super::imp::OnceCell as Imp;
/// A thread-safe cell which can be written to only once.
///
@@ -1047,7 +1081,7 @@ pub mod sync {
/// ```
pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
let mut value = Some(value);
- let res = self.get_or_init(|| unsafe { unwrap_unchecked(value.take()) });
+ let res = self.get_or_init(|| unsafe { value.take().unwrap_unchecked() });
match value {
None => Ok(res),
Some(value) => Err((res, value)),
@@ -1163,7 +1197,7 @@ pub mod sync {
/// cell = OnceCell::new();
/// ```
pub fn take(&mut self) -> Option<T> {
- mem::replace(self, Self::default()).into_inner()
+ mem::take(self).into_inner()
}
/// Consumes the `OnceCell`, returning the wrapped value. Returns
@@ -1293,8 +1327,14 @@ pub mod sync {
/// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92);
/// ```
pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T {
- Self::force(this);
- Self::get_mut(this).unwrap_or_else(|| unreachable!())
+ if this.cell.get_mut().is_none() {
+ let value = match this.init.get_mut().take() {
+ Some(f) => f(),
+ None => panic!("Lazy instance has previously been poisoned"),
+ };
+ this.cell = OnceCell::with_value(value);
+ }
+ this.cell.get_mut().unwrap_or_else(|| unreachable!())
}
/// Gets the reference to the result of this lazy value if
@@ -1341,8 +1381,7 @@ pub mod sync {
impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> {
fn deref_mut(&mut self) -> &mut T {
- Lazy::force(self);
- self.cell.get_mut().unwrap_or_else(|| unreachable!())
+ Lazy::force_mut(self)
}
}
@@ -1373,15 +1412,3 @@ pub mod sync {
#[cfg(feature = "race")]
pub mod race;
-
-// Remove once MSRV is at least 1.58.
-#[inline]
-unsafe fn unwrap_unchecked<T>(val: Option<T>) -> T {
- match val {
- Some(value) => value,
- None => {
- debug_assert!(false);
- core::hint::unreachable_unchecked()
- }
- }
-}
diff --git a/vendor/once_cell/src/race.rs b/vendor/once_cell/src/race.rs
index ee3d51a58..fe36fa174 100644
--- a/vendor/once_cell/src/race.rs
+++ b/vendor/once_cell/src/race.rs
@@ -351,7 +351,7 @@ mod once_box {
Ordering::AcqRel,
Ordering::Acquire,
);
- if let Err(_) = exchange {
+ if exchange.is_err() {
let value = unsafe { Box::from_raw(ptr) };
return Err(value);
}
diff --git a/vendor/once_cell/tests/it.rs b/vendor/once_cell/tests/it.rs
deleted file mode 100644
index d18f0a165..000000000
--- a/vendor/once_cell/tests/it.rs
+++ /dev/null
@@ -1,977 +0,0 @@
-mod unsync {
- use core::{
- cell::Cell,
- sync::atomic::{AtomicUsize, Ordering::SeqCst},
- };
-
- use once_cell::unsync::{Lazy, OnceCell};
-
- #[test]
- fn once_cell() {
- let c = OnceCell::new();
- assert!(c.get().is_none());
- c.get_or_init(|| 92);
- assert_eq!(c.get(), Some(&92));
-
- c.get_or_init(|| panic!("Kabom!"));
- assert_eq!(c.get(), Some(&92));
- }
-
- #[test]
- fn once_cell_with_value() {
- const CELL: OnceCell<i32> = OnceCell::with_value(12);
- let cell = CELL;
- assert_eq!(cell.get(), Some(&12));
- }
-
- #[test]
- fn once_cell_get_mut() {
- let mut c = OnceCell::new();
- assert!(c.get_mut().is_none());
- c.set(90).unwrap();
- *c.get_mut().unwrap() += 2;
- assert_eq!(c.get_mut(), Some(&mut 92));
- }
-
- #[test]
- fn once_cell_drop() {
- static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
- struct Dropper;
- impl Drop for Dropper {
- fn drop(&mut self) {
- DROP_CNT.fetch_add(1, SeqCst);
- }
- }
-
- let x = OnceCell::new();
- x.get_or_init(|| Dropper);
- assert_eq!(DROP_CNT.load(SeqCst), 0);
- drop(x);
- assert_eq!(DROP_CNT.load(SeqCst), 1);
- }
-
- #[test]
- fn unsync_once_cell_drop_empty() {
- let x = OnceCell::<String>::new();
- drop(x);
- }
-
- #[test]
- fn clone() {
- let s = OnceCell::new();
- let c = s.clone();
- assert!(c.get().is_none());
-
- s.set("hello".to_string()).unwrap();
- let c = s.clone();
- assert_eq!(c.get().map(String::as_str), Some("hello"));
- }
-
- #[test]
- fn from_impl() {
- assert_eq!(OnceCell::from("value").get(), Some(&"value"));
- assert_ne!(OnceCell::from("foo").get(), Some(&"bar"));
- }
-
- #[test]
- fn partialeq_impl() {
- assert!(OnceCell::from("value") == OnceCell::from("value"));
- assert!(OnceCell::from("foo") != OnceCell::from("bar"));
-
- assert!(OnceCell::<String>::new() == OnceCell::new());
- assert!(OnceCell::<String>::new() != OnceCell::from("value".to_owned()));
- }
-
- #[test]
- fn into_inner() {
- 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()));
- }
-
- #[test]
- fn debug_impl() {
- let cell = OnceCell::new();
- assert_eq!(format!("{:?}", cell), "OnceCell(Uninit)");
- cell.set("hello".to_string()).unwrap();
- assert_eq!(format!("{:?}", cell), "OnceCell(\"hello\")");
- }
-
- #[test]
- fn lazy_new() {
- let called = Cell::new(0);
- let x = Lazy::new(|| {
- called.set(called.get() + 1);
- 92
- });
-
- assert_eq!(called.get(), 0);
-
- let y = *x - 30;
- assert_eq!(y, 62);
- assert_eq!(called.get(), 1);
-
- let y = *x - 30;
- assert_eq!(y, 62);
- assert_eq!(called.get(), 1);
- }
-
- #[test]
- fn lazy_deref_mut() {
- let called = Cell::new(0);
- let mut x = Lazy::new(|| {
- called.set(called.get() + 1);
- 92
- });
-
- assert_eq!(called.get(), 0);
-
- let y = *x - 30;
- assert_eq!(y, 62);
- assert_eq!(called.get(), 1);
-
- *x /= 2;
- assert_eq!(*x, 46);
- assert_eq!(called.get(), 1);
- }
-
- #[test]
- fn lazy_force_mut() {
- let called = Cell::new(0);
- let mut x = Lazy::new(|| {
- called.set(called.get() + 1);
- 92
- });
- assert_eq!(called.get(), 0);
- let v = Lazy::force_mut(&mut x);
- assert_eq!(called.get(), 1);
-
- *v /= 2;
- assert_eq!(*x, 46);
- assert_eq!(called.get(), 1);
- }
-
- #[test]
- fn lazy_get_mut() {
- let called = Cell::new(0);
- let mut x: Lazy<u32, _> = Lazy::new(|| {
- called.set(called.get() + 1);
- 92
- });
-
- assert_eq!(called.get(), 0);
- assert_eq!(*x, 92);
-
- let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap();
- assert_eq!(called.get(), 1);
-
- *mut_ref /= 2;
- assert_eq!(*x, 46);
- assert_eq!(called.get(), 1);
- }
-
- #[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<std::sync::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_into_value() {
- let l: Lazy<i32, _> = Lazy::new(|| panic!());
- assert!(matches!(Lazy::into_value(l), Err(_)));
- let l = Lazy::new(|| -> i32 { 92 });
- Lazy::force(&l);
- assert!(matches!(Lazy::into_value(l), Ok(92)));
- }
-
- #[test]
- #[cfg(feature = "std")]
- fn lazy_poisoning() {
- let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
- for _ in 0..2 {
- let res = std::panic::catch_unwind(|| x.len());
- assert!(res.is_err());
- }
- }
-
- #[test]
- fn aliasing_in_get() {
- let x = OnceCell::new();
- x.set(42).unwrap();
- let at_x = x.get().unwrap(); // --- (shared) borrow of inner `Option<T>` --+
- let _ = x.set(27); // <-- temporary (unique) borrow of inner `Option<T>` |
- println!("{}", at_x); // <------- up until here ---------------------------+
- }
-
- #[test]
- #[should_panic(expected = "reentrant init")]
- fn reentrant_init() {
- let x: OnceCell<Box<i32>> = OnceCell::new();
- let dangling_ref: Cell<Option<&i32>> = Cell::new(None);
- x.get_or_init(|| {
- let r = x.get_or_init(|| Box::new(92));
- dangling_ref.set(Some(r));
- Box::new(62)
- });
- eprintln!("use after free: {:?}", dangling_ref.get().unwrap());
- }
-
- #[test]
- // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
- fn arrrrrrrrrrrrrrrrrrrrrr() {
- let cell = OnceCell::new();
- {
- let s = String::new();
- cell.set(&s).unwrap();
- }
- }
-}
-
-#[cfg(any(feature = "std", feature = "critical-section"))]
-mod sync {
- use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
-
- #[cfg(feature = "std")]
- use std::sync::Barrier;
-
- #[cfg(not(feature = "std"))]
- use core::cell::Cell;
-
- use crossbeam_utils::thread::scope;
-
- use once_cell::sync::{Lazy, OnceCell};
-
- #[test]
- fn once_cell() {
- let c = OnceCell::new();
- assert!(c.get().is_none());
- scope(|s| {
- s.spawn(|_| {
- c.get_or_init(|| 92);
- assert_eq!(c.get(), Some(&92));
- });
- })
- .unwrap();
- c.get_or_init(|| panic!("Kabom!"));
- assert_eq!(c.get(), Some(&92));
- }
-
- #[test]
- fn once_cell_with_value() {
- static CELL: OnceCell<i32> = OnceCell::with_value(12);
- assert_eq!(CELL.get(), Some(&12));
- }
-
- #[test]
- fn once_cell_get_mut() {
- let mut c = OnceCell::new();
- assert!(c.get_mut().is_none());
- c.set(90).unwrap();
- *c.get_mut().unwrap() += 2;
- assert_eq!(c.get_mut(), Some(&mut 92));
- }
-
- #[test]
- fn once_cell_get_unchecked() {
- let c = OnceCell::new();
- c.set(92).unwrap();
- unsafe {
- assert_eq!(c.get_unchecked(), &92);
- }
- }
-
- #[test]
- fn once_cell_drop() {
- static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
- struct Dropper;
- impl Drop for Dropper {
- fn drop(&mut self) {
- DROP_CNT.fetch_add(1, SeqCst);
- }
- }
-
- let x = OnceCell::new();
- scope(|s| {
- s.spawn(|_| {
- x.get_or_init(|| Dropper);
- assert_eq!(DROP_CNT.load(SeqCst), 0);
- drop(x);
- });
- })
- .unwrap();
- assert_eq!(DROP_CNT.load(SeqCst), 1);
- }
-
- #[test]
- fn once_cell_drop_empty() {
- let x = OnceCell::<String>::new();
- drop(x);
- }
-
- #[test]
- fn clone() {
- let s = OnceCell::new();
- let c = s.clone();
- assert!(c.get().is_none());
-
- s.set("hello".to_string()).unwrap();
- let c = s.clone();
- assert_eq!(c.get().map(String::as_str), Some("hello"));
- }
-
- #[test]
- fn get_or_try_init() {
- let cell: OnceCell<String> = OnceCell::new();
- assert!(cell.get().is_none());
-
- let res =
- std::panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() }));
- assert!(res.is_err());
- assert!(cell.get().is_none());
-
- assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
-
- assert_eq!(
- cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())),
- Ok(&"hello".to_string())
- );
- assert_eq!(cell.get(), Some(&"hello".to_string()));
- }
-
- #[cfg(feature = "std")]
- #[test]
- fn wait() {
- let cell: OnceCell<String> = OnceCell::new();
- scope(|s| {
- s.spawn(|_| cell.set("hello".to_string()));
- let greeting = cell.wait();
- assert_eq!(greeting, "hello")
- })
- .unwrap();
- }
-
- #[cfg(feature = "std")]
- #[test]
- fn get_or_init_stress() {
- let n_threads = if cfg!(miri) { 30 } else { 1_000 };
- let n_cells = if cfg!(miri) { 30 } else { 1_000 };
- let cells: Vec<_> = std::iter::repeat_with(|| (Barrier::new(n_threads), OnceCell::new()))
- .take(n_cells)
- .collect();
- scope(|s| {
- for t in 0..n_threads {
- let cells = &cells;
- s.spawn(move |_| {
- for (i, (b, s)) in cells.iter().enumerate() {
- b.wait();
- let j = if t % 2 == 0 { s.wait() } else { s.get_or_init(|| i) };
- assert_eq!(*j, i);
- }
- });
- }
- })
- .unwrap();
- }
-
- #[test]
- fn from_impl() {
- assert_eq!(OnceCell::from("value").get(), Some(&"value"));
- assert_ne!(OnceCell::from("foo").get(), Some(&"bar"));
- }
-
- #[test]
- fn partialeq_impl() {
- assert!(OnceCell::from("value") == OnceCell::from("value"));
- assert!(OnceCell::from("foo") != OnceCell::from("bar"));
-
- assert!(OnceCell::<String>::new() == OnceCell::new());
- assert!(OnceCell::<String>::new() != OnceCell::from("value".to_owned()));
- }
-
- #[test]
- fn into_inner() {
- 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()));
- }
-
- #[test]
- fn debug_impl() {
- let cell = OnceCell::new();
- assert_eq!(format!("{:#?}", cell), "OnceCell(Uninit)");
- cell.set(vec!["hello", "world"]).unwrap();
- assert_eq!(
- format!("{:#?}", cell),
- r#"OnceCell(
- [
- "hello",
- "world",
- ],
-)"#
- );
- }
-
- #[test]
- #[cfg_attr(miri, ignore)] // miri doesn't support processes
- #[cfg(feature = "std")]
- fn reentrant_init() {
- let examples_dir = {
- let mut exe = std::env::current_exe().unwrap();
- exe.pop();
- exe.pop();
- exe.push("examples");
- exe
- };
- let bin = examples_dir
- .join("reentrant_init_deadlocks")
- .with_extension(std::env::consts::EXE_EXTENSION);
- let mut guard = Guard { child: std::process::Command::new(bin).spawn().unwrap() };
- std::thread::sleep(std::time::Duration::from_secs(2));
- let status = guard.child.try_wait().unwrap();
- assert!(status.is_none());
-
- struct Guard {
- child: std::process::Child,
- }
-
- impl Drop for Guard {
- fn drop(&mut self) {
- let _ = self.child.kill();
- }
- }
- }
-
- #[cfg(not(feature = "std"))]
- #[test]
- #[should_panic(expected = "reentrant init")]
- fn reentrant_init() {
- let x: OnceCell<Box<i32>> = OnceCell::new();
- let dangling_ref: Cell<Option<&i32>> = Cell::new(None);
- x.get_or_init(|| {
- let r = x.get_or_init(|| Box::new(92));
- dangling_ref.set(Some(r));
- Box::new(62)
- });
- eprintln!("use after free: {:?}", dangling_ref.get().unwrap());
- }
-
- #[test]
- fn lazy_new() {
- let called = AtomicUsize::new(0);
- let x = Lazy::new(|| {
- called.fetch_add(1, SeqCst);
- 92
- });
-
- assert_eq!(called.load(SeqCst), 0);
-
- scope(|s| {
- s.spawn(|_| {
- let y = *x - 30;
- assert_eq!(y, 62);
- assert_eq!(called.load(SeqCst), 1);
- });
- })
- .unwrap();
-
- let y = *x - 30;
- assert_eq!(y, 62);
- assert_eq!(called.load(SeqCst), 1);
- }
-
- #[test]
- fn lazy_deref_mut() {
- let called = AtomicUsize::new(0);
- let mut x = Lazy::new(|| {
- called.fetch_add(1, SeqCst);
- 92
- });
-
- assert_eq!(called.load(SeqCst), 0);
-
- let y = *x - 30;
- assert_eq!(y, 62);
- assert_eq!(called.load(SeqCst), 1);
-
- *x /= 2;
- assert_eq!(*x, 46);
- assert_eq!(called.load(SeqCst), 1);
- }
-
- #[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<std::sync::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 static_lazy() {
- static XS: Lazy<Vec<i32>> = Lazy::new(|| {
- let mut xs = Vec::new();
- xs.push(1);
- xs.push(2);
- xs.push(3);
- xs
- });
- scope(|s| {
- s.spawn(|_| {
- assert_eq!(&*XS, &vec![1, 2, 3]);
- });
- })
- .unwrap();
- assert_eq!(&*XS, &vec![1, 2, 3]);
- }
-
- #[test]
- fn static_lazy_via_fn() {
- fn xs() -> &'static Vec<i32> {
- static XS: OnceCell<Vec<i32>> = OnceCell::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 lazy_into_value() {
- let l: Lazy<i32, _> = Lazy::new(|| panic!());
- assert!(matches!(Lazy::into_value(l), Err(_)));
- let l = Lazy::new(|| -> i32 { 92 });
- Lazy::force(&l);
- assert!(matches!(Lazy::into_value(l), Ok(92)));
- }
-
- #[test]
- fn lazy_poisoning() {
- let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
- for _ in 0..2 {
- let res = std::panic::catch_unwind(|| x.len());
- assert!(res.is_err());
- }
- }
-
- #[test]
- fn once_cell_is_sync_send() {
- fn assert_traits<T: Send + Sync>() {}
- assert_traits::<OnceCell<String>>();
- assert_traits::<Lazy<String>>();
- }
-
- #[test]
- fn eval_once_macro() {
- macro_rules! eval_once {
- (|| -> $ty:ty {
- $($body:tt)*
- }) => {{
- static ONCE_CELL: OnceCell<$ty> = OnceCell::new();
- fn init() -> $ty {
- $($body)*
- }
- ONCE_CELL.get_or_init(init)
- }};
- }
-
- let fib: &'static Vec<i32> = eval_once! {
- || -> Vec<i32> {
- let mut res = vec![1, 1];
- for i in 0..10 {
- let next = res[i] + res[i + 1];
- res.push(next);
- }
- res
- }
- };
- assert_eq!(fib[5], 8)
- }
-
- #[test]
- fn once_cell_does_not_leak_partially_constructed_boxes() {
- let n_tries = if cfg!(miri) { 10 } else { 100 };
- let n_readers = 10;
- let n_writers = 3;
- const MSG: &str = "Hello, World";
-
- for _ in 0..n_tries {
- let cell: OnceCell<String> = OnceCell::new();
- scope(|scope| {
- for _ in 0..n_readers {
- scope.spawn(|_| loop {
- if let Some(msg) = cell.get() {
- assert_eq!(msg, MSG);
- break;
- }
- });
- }
- for _ in 0..n_writers {
- let _ = scope.spawn(|_| cell.set(MSG.to_owned()));
- }
- })
- .unwrap()
- }
- }
-
- #[cfg(feature = "std")]
- #[test]
- fn get_does_not_block() {
- let cell = OnceCell::new();
- let barrier = Barrier::new(2);
- scope(|scope| {
- scope.spawn(|_| {
- cell.get_or_init(|| {
- barrier.wait();
- barrier.wait();
- "hello".to_string()
- });
- });
- barrier.wait();
- assert_eq!(cell.get(), None);
- barrier.wait();
- })
- .unwrap();
- assert_eq!(cell.get(), Some(&"hello".to_string()));
- }
-
- #[test]
- // https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
- fn arrrrrrrrrrrrrrrrrrrrrr() {
- let cell = OnceCell::new();
- {
- let s = String::new();
- cell.set(&s).unwrap();
- }
- }
-}
-
-#[cfg(feature = "race")]
-mod race {
- #[cfg(feature = "std")]
- use std::sync::Barrier;
- use std::{
- num::NonZeroUsize,
- sync::atomic::{AtomicUsize, Ordering::SeqCst},
- };
-
- use crossbeam_utils::thread::scope;
-
- use once_cell::race::{OnceBool, OnceNonZeroUsize};
-
- #[test]
- fn once_non_zero_usize_smoke_test() {
- let cnt = AtomicUsize::new(0);
- let cell = OnceNonZeroUsize::new();
- let val = NonZeroUsize::new(92).unwrap();
- scope(|s| {
- s.spawn(|_| {
- assert_eq!(
- cell.get_or_init(|| {
- cnt.fetch_add(1, SeqCst);
- val
- }),
- val
- );
- assert_eq!(cnt.load(SeqCst), 1);
-
- assert_eq!(
- cell.get_or_init(|| {
- cnt.fetch_add(1, SeqCst);
- val
- }),
- val
- );
- assert_eq!(cnt.load(SeqCst), 1);
- });
- })
- .unwrap();
- assert_eq!(cell.get(), Some(val));
- assert_eq!(cnt.load(SeqCst), 1);
- }
-
- #[test]
- fn once_non_zero_usize_set() {
- let val1 = NonZeroUsize::new(92).unwrap();
- let val2 = NonZeroUsize::new(62).unwrap();
-
- let cell = OnceNonZeroUsize::new();
-
- assert!(cell.set(val1).is_ok());
- assert_eq!(cell.get(), Some(val1));
-
- assert!(cell.set(val2).is_err());
- assert_eq!(cell.get(), Some(val1));
- }
-
- #[cfg(feature = "std")]
- #[test]
- fn once_non_zero_usize_first_wins() {
- let val1 = NonZeroUsize::new(92).unwrap();
- let val2 = NonZeroUsize::new(62).unwrap();
-
- let cell = OnceNonZeroUsize::new();
-
- let b1 = Barrier::new(2);
- let b2 = Barrier::new(2);
- let b3 = Barrier::new(2);
- scope(|s| {
- s.spawn(|_| {
- let r1 = cell.get_or_init(|| {
- b1.wait();
- b2.wait();
- val1
- });
- assert_eq!(r1, val1);
- b3.wait();
- });
- b1.wait();
- s.spawn(|_| {
- let r2 = cell.get_or_init(|| {
- b2.wait();
- b3.wait();
- val2
- });
- assert_eq!(r2, val1);
- });
- })
- .unwrap();
-
- assert_eq!(cell.get(), Some(val1));
- }
-
- #[test]
- fn once_bool_smoke_test() {
- let cnt = AtomicUsize::new(0);
- let cell = OnceBool::new();
- scope(|s| {
- s.spawn(|_| {
- assert_eq!(
- cell.get_or_init(|| {
- cnt.fetch_add(1, SeqCst);
- false
- }),
- false
- );
- assert_eq!(cnt.load(SeqCst), 1);
-
- assert_eq!(
- cell.get_or_init(|| {
- cnt.fetch_add(1, SeqCst);
- false
- }),
- false
- );
- assert_eq!(cnt.load(SeqCst), 1);
- });
- })
- .unwrap();
- assert_eq!(cell.get(), Some(false));
- assert_eq!(cnt.load(SeqCst), 1);
- }
-
- #[test]
- fn once_bool_set() {
- let cell = OnceBool::new();
-
- assert!(cell.set(false).is_ok());
- assert_eq!(cell.get(), Some(false));
-
- assert!(cell.set(true).is_err());
- assert_eq!(cell.get(), Some(false));
- }
-}
-
-#[cfg(all(feature = "race", feature = "alloc"))]
-mod race_once_box {
- #[cfg(feature = "std")]
- use std::sync::Barrier;
- use std::sync::{
- atomic::{AtomicUsize, Ordering::SeqCst},
- Arc,
- };
-
- #[cfg(feature = "std")]
- use crossbeam_utils::thread::scope;
-
- use once_cell::race::OnceBox;
-
- #[derive(Default)]
- struct Heap {
- total: Arc<AtomicUsize>,
- }
-
- #[derive(Debug)]
- struct Pebble<T> {
- val: T,
- total: Arc<AtomicUsize>,
- }
-
- impl<T> Drop for Pebble<T> {
- fn drop(&mut self) {
- self.total.fetch_sub(1, SeqCst);
- }
- }
-
- impl Heap {
- fn total(&self) -> usize {
- self.total.load(SeqCst)
- }
- fn new_pebble<T>(&self, val: T) -> Pebble<T> {
- self.total.fetch_add(1, SeqCst);
- Pebble { val, total: Arc::clone(&self.total) }
- }
- }
-
- #[cfg(feature = "std")]
- #[test]
- fn once_box_smoke_test() {
- let heap = Heap::default();
- let global_cnt = AtomicUsize::new(0);
- let cell = OnceBox::new();
- let b = Barrier::new(128);
- scope(|s| {
- for _ in 0..128 {
- s.spawn(|_| {
- let local_cnt = AtomicUsize::new(0);
- cell.get_or_init(|| {
- global_cnt.fetch_add(1, SeqCst);
- local_cnt.fetch_add(1, SeqCst);
- b.wait();
- Box::new(heap.new_pebble(()))
- });
- assert_eq!(local_cnt.load(SeqCst), 1);
-
- cell.get_or_init(|| {
- global_cnt.fetch_add(1, SeqCst);
- local_cnt.fetch_add(1, SeqCst);
- Box::new(heap.new_pebble(()))
- });
- assert_eq!(local_cnt.load(SeqCst), 1);
- });
- }
- })
- .unwrap();
- assert!(cell.get().is_some());
- assert!(global_cnt.load(SeqCst) > 10);
-
- assert_eq!(heap.total(), 1);
- drop(cell);
- assert_eq!(heap.total(), 0);
- }
-
- #[test]
- fn once_box_set() {
- let heap = Heap::default();
- let cell = OnceBox::new();
- assert!(cell.get().is_none());
-
- assert!(cell.set(Box::new(heap.new_pebble("hello"))).is_ok());
- assert_eq!(cell.get().unwrap().val, "hello");
- assert_eq!(heap.total(), 1);
-
- assert!(cell.set(Box::new(heap.new_pebble("world"))).is_err());
- assert_eq!(cell.get().unwrap().val, "hello");
- assert_eq!(heap.total(), 1);
-
- drop(cell);
- assert_eq!(heap.total(), 0);
- }
-
- #[cfg(feature = "std")]
- #[test]
- fn once_box_first_wins() {
- let cell = OnceBox::new();
- let val1 = 92;
- let val2 = 62;
-
- let b1 = Barrier::new(2);
- let b2 = Barrier::new(2);
- let b3 = Barrier::new(2);
- scope(|s| {
- s.spawn(|_| {
- let r1 = cell.get_or_init(|| {
- b1.wait();
- b2.wait();
- Box::new(val1)
- });
- assert_eq!(*r1, val1);
- b3.wait();
- });
- b1.wait();
- s.spawn(|_| {
- let r2 = cell.get_or_init(|| {
- b2.wait();
- b3.wait();
- Box::new(val2)
- });
- assert_eq!(*r2, val1);
- });
- })
- .unwrap();
-
- assert_eq!(cell.get(), Some(&val1));
- }
-
- #[test]
- fn once_box_reentrant() {
- let cell = OnceBox::new();
- let res = cell.get_or_init(|| {
- cell.get_or_init(|| Box::new("hello".to_string()));
- Box::new("world".to_string())
- });
- assert_eq!(res, "hello");
- }
-
- #[test]
- fn once_box_default() {
- struct Foo;
-
- let cell: OnceBox<Foo> = Default::default();
- assert!(cell.get().is_none());
- }
-}
diff --git a/vendor/once_cell/tests/it/main.rs b/vendor/once_cell/tests/it/main.rs
new file mode 100644
index 000000000..b8e56ccc6
--- /dev/null
+++ b/vendor/once_cell/tests/it/main.rs
@@ -0,0 +1,12 @@
+mod unsync_once_cell;
+#[cfg(any(feature = "std", feature = "critical-section"))]
+mod sync_once_cell;
+
+mod unsync_lazy;
+#[cfg(any(feature = "std", feature = "critical-section"))]
+mod sync_lazy;
+
+#[cfg(feature = "race")]
+mod race;
+#[cfg(all(feature = "race", feature = "alloc"))]
+mod race_once_box;
diff --git a/vendor/once_cell/tests/it/race.rs b/vendor/once_cell/tests/it/race.rs
new file mode 100644
index 000000000..24884dd82
--- /dev/null
+++ b/vendor/once_cell/tests/it/race.rs
@@ -0,0 +1,128 @@
+#[cfg(feature = "std")]
+use std::sync::Barrier;
+use std::{
+ num::NonZeroUsize,
+ sync::atomic::{AtomicUsize, Ordering::SeqCst},
+ thread::scope,
+};
+
+use once_cell::race::{OnceBool, OnceNonZeroUsize};
+
+#[test]
+fn once_non_zero_usize_smoke_test() {
+ let cnt = AtomicUsize::new(0);
+ let cell = OnceNonZeroUsize::new();
+ let val = NonZeroUsize::new(92).unwrap();
+ scope(|s| {
+ s.spawn(|| {
+ assert_eq!(
+ cell.get_or_init(|| {
+ cnt.fetch_add(1, SeqCst);
+ val
+ }),
+ val
+ );
+ assert_eq!(cnt.load(SeqCst), 1);
+
+ assert_eq!(
+ cell.get_or_init(|| {
+ cnt.fetch_add(1, SeqCst);
+ val
+ }),
+ val
+ );
+ assert_eq!(cnt.load(SeqCst), 1);
+ });
+ });
+ assert_eq!(cell.get(), Some(val));
+ assert_eq!(cnt.load(SeqCst), 1);
+}
+
+#[test]
+fn once_non_zero_usize_set() {
+ let val1 = NonZeroUsize::new(92).unwrap();
+ let val2 = NonZeroUsize::new(62).unwrap();
+
+ let cell = OnceNonZeroUsize::new();
+
+ assert!(cell.set(val1).is_ok());
+ assert_eq!(cell.get(), Some(val1));
+
+ assert!(cell.set(val2).is_err());
+ assert_eq!(cell.get(), Some(val1));
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn once_non_zero_usize_first_wins() {
+ let val1 = NonZeroUsize::new(92).unwrap();
+ let val2 = NonZeroUsize::new(62).unwrap();
+
+ let cell = OnceNonZeroUsize::new();
+
+ let b1 = Barrier::new(2);
+ let b2 = Barrier::new(2);
+ let b3 = Barrier::new(2);
+ scope(|s| {
+ s.spawn(|| {
+ let r1 = cell.get_or_init(|| {
+ b1.wait();
+ b2.wait();
+ val1
+ });
+ assert_eq!(r1, val1);
+ b3.wait();
+ });
+ b1.wait();
+ s.spawn(|| {
+ let r2 = cell.get_or_init(|| {
+ b2.wait();
+ b3.wait();
+ val2
+ });
+ assert_eq!(r2, val1);
+ });
+ });
+
+ assert_eq!(cell.get(), Some(val1));
+}
+
+#[test]
+fn once_bool_smoke_test() {
+ let cnt = AtomicUsize::new(0);
+ let cell = OnceBool::new();
+ scope(|s| {
+ s.spawn(|| {
+ assert_eq!(
+ cell.get_or_init(|| {
+ cnt.fetch_add(1, SeqCst);
+ false
+ }),
+ false
+ );
+ assert_eq!(cnt.load(SeqCst), 1);
+
+ assert_eq!(
+ cell.get_or_init(|| {
+ cnt.fetch_add(1, SeqCst);
+ false
+ }),
+ false
+ );
+ assert_eq!(cnt.load(SeqCst), 1);
+ });
+ });
+ assert_eq!(cell.get(), Some(false));
+ assert_eq!(cnt.load(SeqCst), 1);
+}
+
+#[test]
+fn once_bool_set() {
+ let cell = OnceBool::new();
+
+ assert!(cell.set(false).is_ok());
+ assert_eq!(cell.get(), Some(false));
+
+ assert!(cell.set(true).is_err());
+ assert_eq!(cell.get(), Some(false));
+}
diff --git a/vendor/once_cell/tests/it/race_once_box.rs b/vendor/once_cell/tests/it/race_once_box.rs
new file mode 100644
index 000000000..0bf3852d7
--- /dev/null
+++ b/vendor/once_cell/tests/it/race_once_box.rs
@@ -0,0 +1,145 @@
+#[cfg(feature = "std")]
+use std::sync::Barrier;
+use std::sync::{
+ atomic::{AtomicUsize, Ordering::SeqCst},
+ Arc,
+};
+
+use once_cell::race::OnceBox;
+
+#[derive(Default)]
+struct Heap {
+ total: Arc<AtomicUsize>,
+}
+
+#[derive(Debug)]
+struct Pebble<T> {
+ val: T,
+ total: Arc<AtomicUsize>,
+}
+
+impl<T> Drop for Pebble<T> {
+ fn drop(&mut self) {
+ self.total.fetch_sub(1, SeqCst);
+ }
+}
+
+impl Heap {
+ fn total(&self) -> usize {
+ self.total.load(SeqCst)
+ }
+ fn new_pebble<T>(&self, val: T) -> Pebble<T> {
+ self.total.fetch_add(1, SeqCst);
+ Pebble { val, total: Arc::clone(&self.total) }
+ }
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn once_box_smoke_test() {
+ use std::thread::scope;
+
+ let heap = Heap::default();
+ let global_cnt = AtomicUsize::new(0);
+ let cell = OnceBox::new();
+ let b = Barrier::new(128);
+ scope(|s| {
+ for _ in 0..128 {
+ s.spawn(|| {
+ let local_cnt = AtomicUsize::new(0);
+ cell.get_or_init(|| {
+ global_cnt.fetch_add(1, SeqCst);
+ local_cnt.fetch_add(1, SeqCst);
+ b.wait();
+ Box::new(heap.new_pebble(()))
+ });
+ assert_eq!(local_cnt.load(SeqCst), 1);
+
+ cell.get_or_init(|| {
+ global_cnt.fetch_add(1, SeqCst);
+ local_cnt.fetch_add(1, SeqCst);
+ Box::new(heap.new_pebble(()))
+ });
+ assert_eq!(local_cnt.load(SeqCst), 1);
+ });
+ }
+ });
+ assert!(cell.get().is_some());
+ assert!(global_cnt.load(SeqCst) > 10);
+
+ assert_eq!(heap.total(), 1);
+ drop(cell);
+ assert_eq!(heap.total(), 0);
+}
+
+#[test]
+fn once_box_set() {
+ let heap = Heap::default();
+ let cell = OnceBox::new();
+ assert!(cell.get().is_none());
+
+ assert!(cell.set(Box::new(heap.new_pebble("hello"))).is_ok());
+ assert_eq!(cell.get().unwrap().val, "hello");
+ assert_eq!(heap.total(), 1);
+
+ assert!(cell.set(Box::new(heap.new_pebble("world"))).is_err());
+ assert_eq!(cell.get().unwrap().val, "hello");
+ assert_eq!(heap.total(), 1);
+
+ drop(cell);
+ assert_eq!(heap.total(), 0);
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn once_box_first_wins() {
+ use std::thread::scope;
+
+ let cell = OnceBox::new();
+ let val1 = 92;
+ let val2 = 62;
+
+ let b1 = Barrier::new(2);
+ let b2 = Barrier::new(2);
+ let b3 = Barrier::new(2);
+ scope(|s| {
+ s.spawn(|| {
+ let r1 = cell.get_or_init(|| {
+ b1.wait();
+ b2.wait();
+ Box::new(val1)
+ });
+ assert_eq!(*r1, val1);
+ b3.wait();
+ });
+ b1.wait();
+ s.spawn(|| {
+ let r2 = cell.get_or_init(|| {
+ b2.wait();
+ b3.wait();
+ Box::new(val2)
+ });
+ assert_eq!(*r2, val1);
+ });
+ });
+
+ assert_eq!(cell.get(), Some(&val1));
+}
+
+#[test]
+fn once_box_reentrant() {
+ let cell = OnceBox::new();
+ let res = cell.get_or_init(|| {
+ cell.get_or_init(|| Box::new("hello".to_string()));
+ Box::new("world".to_string())
+ });
+ assert_eq!(res, "hello");
+}
+
+#[test]
+fn once_box_default() {
+ struct Foo;
+
+ let cell: OnceBox<Foo> = Default::default();
+ assert!(cell.get().is_none());
+}
diff --git a/vendor/once_cell/tests/it/sync_lazy.rs b/vendor/once_cell/tests/it/sync_lazy.rs
new file mode 100644
index 000000000..44d70fa0c
--- /dev/null
+++ b/vendor/once_cell/tests/it/sync_lazy.rs
@@ -0,0 +1,176 @@
+use std::{
+ cell::Cell,
+ sync::atomic::{AtomicUsize, Ordering::SeqCst},
+ thread::scope,
+};
+
+use once_cell::sync::{Lazy, OnceCell};
+
+#[test]
+fn lazy_new() {
+ let called = AtomicUsize::new(0);
+ let x = Lazy::new(|| {
+ called.fetch_add(1, SeqCst);
+ 92
+ });
+
+ assert_eq!(called.load(SeqCst), 0);
+
+ scope(|s| {
+ s.spawn(|| {
+ let y = *x - 30;
+ assert_eq!(y, 62);
+ assert_eq!(called.load(SeqCst), 1);
+ });
+ });
+
+ let y = *x - 30;
+ assert_eq!(y, 62);
+ assert_eq!(called.load(SeqCst), 1);
+}
+
+#[test]
+fn lazy_deref_mut() {
+ let called = AtomicUsize::new(0);
+ let mut x = Lazy::new(|| {
+ called.fetch_add(1, SeqCst);
+ 92
+ });
+
+ assert_eq!(called.load(SeqCst), 0);
+
+ let y = *x - 30;
+ assert_eq!(y, 62);
+ assert_eq!(called.load(SeqCst), 1);
+
+ *x /= 2;
+ assert_eq!(*x, 46);
+ assert_eq!(called.load(SeqCst), 1);
+}
+
+#[test]
+fn lazy_force_mut() {
+ let called = Cell::new(0);
+ let mut x = Lazy::new(|| {
+ called.set(called.get() + 1);
+ 92
+ });
+ assert_eq!(called.get(), 0);
+ let v = Lazy::force_mut(&mut x);
+ assert_eq!(called.get(), 1);
+
+ *v /= 2;
+ assert_eq!(*x, 46);
+ assert_eq!(called.get(), 1);
+}
+
+#[test]
+fn lazy_get_mut() {
+ let called = Cell::new(0);
+ let mut x: Lazy<u32, _> = Lazy::new(|| {
+ called.set(called.get() + 1);
+ 92
+ });
+
+ assert_eq!(called.get(), 0);
+ assert_eq!(*x, 92);
+
+ let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap();
+ assert_eq!(called.get(), 1);
+
+ *mut_ref /= 2;
+ assert_eq!(*x, 46);
+ assert_eq!(called.get(), 1);
+}
+
+#[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<std::sync::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 static_lazy() {
+ static XS: Lazy<Vec<i32>> = Lazy::new(|| {
+ let mut xs = Vec::new();
+ xs.push(1);
+ xs.push(2);
+ xs.push(3);
+ xs
+ });
+ scope(|s| {
+ s.spawn(|| {
+ assert_eq!(&*XS, &vec![1, 2, 3]);
+ });
+ });
+ assert_eq!(&*XS, &vec![1, 2, 3]);
+}
+
+#[test]
+fn static_lazy_via_fn() {
+ fn xs() -> &'static Vec<i32> {
+ static XS: OnceCell<Vec<i32>> = OnceCell::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 lazy_into_value() {
+ let l: Lazy<i32, _> = Lazy::new(|| panic!());
+ assert!(matches!(Lazy::into_value(l), Err(_)));
+ let l = Lazy::new(|| -> i32 { 92 });
+ Lazy::force(&l);
+ assert!(matches!(Lazy::into_value(l), Ok(92)));
+}
+
+#[test]
+fn lazy_poisoning() {
+ let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
+ for _ in 0..2 {
+ let res = std::panic::catch_unwind(|| x.len());
+ assert!(res.is_err());
+ }
+}
+
+#[test]
+// https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
+fn arrrrrrrrrrrrrrrrrrrrrr() {
+ let lazy: Lazy<&String, _>;
+ {
+ let s = String::new();
+ lazy = Lazy::new(|| &s);
+ _ = *lazy;
+ }
+}
+
+#[test]
+fn lazy_is_sync_send() {
+ fn assert_traits<T: Send + Sync>() {}
+ assert_traits::<Lazy<String>>();
+}
diff --git a/vendor/once_cell/tests/it/sync_once_cell.rs b/vendor/once_cell/tests/it/sync_once_cell.rs
new file mode 100644
index 000000000..252adeacf
--- /dev/null
+++ b/vendor/once_cell/tests/it/sync_once_cell.rs
@@ -0,0 +1,309 @@
+use std::{
+ sync::atomic::{AtomicUsize, Ordering::SeqCst},
+ thread::scope,
+};
+
+#[cfg(feature = "std")]
+use std::sync::Barrier;
+
+#[cfg(not(feature = "std"))]
+use core::cell::Cell;
+
+use once_cell::sync::{Lazy, OnceCell};
+
+#[test]
+fn once_cell() {
+ let c = OnceCell::new();
+ assert!(c.get().is_none());
+ scope(|s| {
+ s.spawn(|| {
+ c.get_or_init(|| 92);
+ assert_eq!(c.get(), Some(&92));
+ });
+ });
+ c.get_or_init(|| panic!("Kabom!"));
+ assert_eq!(c.get(), Some(&92));
+}
+
+#[test]
+fn once_cell_with_value() {
+ static CELL: OnceCell<i32> = OnceCell::with_value(12);
+ assert_eq!(CELL.get(), Some(&12));
+}
+
+#[test]
+fn once_cell_get_mut() {
+ let mut c = OnceCell::new();
+ assert!(c.get_mut().is_none());
+ c.set(90).unwrap();
+ *c.get_mut().unwrap() += 2;
+ assert_eq!(c.get_mut(), Some(&mut 92));
+}
+
+#[test]
+fn once_cell_get_unchecked() {
+ let c = OnceCell::new();
+ c.set(92).unwrap();
+ unsafe {
+ assert_eq!(c.get_unchecked(), &92);
+ }
+}
+
+#[test]
+fn once_cell_drop() {
+ static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
+ struct Dropper;
+ impl Drop for Dropper {
+ fn drop(&mut self) {
+ DROP_CNT.fetch_add(1, SeqCst);
+ }
+ }
+
+ let x = OnceCell::new();
+ scope(|s| {
+ s.spawn(|| {
+ x.get_or_init(|| Dropper);
+ assert_eq!(DROP_CNT.load(SeqCst), 0);
+ drop(x);
+ });
+ });
+ assert_eq!(DROP_CNT.load(SeqCst), 1);
+}
+
+#[test]
+fn once_cell_drop_empty() {
+ let x = OnceCell::<String>::new();
+ drop(x);
+}
+
+#[test]
+fn clone() {
+ let s = OnceCell::new();
+ let c = s.clone();
+ assert!(c.get().is_none());
+
+ s.set("hello".to_string()).unwrap();
+ let c = s.clone();
+ assert_eq!(c.get().map(String::as_str), Some("hello"));
+}
+
+#[test]
+fn get_or_try_init() {
+ let cell: OnceCell<String> = OnceCell::new();
+ assert!(cell.get().is_none());
+
+ let res = std::panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() }));
+ assert!(res.is_err());
+ assert!(cell.get().is_none());
+
+ assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
+
+ assert_eq!(cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())), Ok(&"hello".to_string()));
+ assert_eq!(cell.get(), Some(&"hello".to_string()));
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn wait() {
+ let cell: OnceCell<String> = OnceCell::new();
+ scope(|s| {
+ s.spawn(|| cell.set("hello".to_string()));
+ let greeting = cell.wait();
+ assert_eq!(greeting, "hello")
+ });
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn get_or_init_stress() {
+ let n_threads = if cfg!(miri) { 30 } else { 1_000 };
+ let n_cells = if cfg!(miri) { 30 } else { 1_000 };
+ let cells: Vec<_> = std::iter::repeat_with(|| (Barrier::new(n_threads), OnceCell::new()))
+ .take(n_cells)
+ .collect();
+ scope(|s| {
+ for t in 0..n_threads {
+ let cells = &cells;
+ s.spawn(move || {
+ for (i, (b, s)) in cells.iter().enumerate() {
+ b.wait();
+ let j = if t % 2 == 0 { s.wait() } else { s.get_or_init(|| i) };
+ assert_eq!(*j, i);
+ }
+ });
+ }
+ });
+}
+
+#[test]
+fn from_impl() {
+ assert_eq!(OnceCell::from("value").get(), Some(&"value"));
+ assert_ne!(OnceCell::from("foo").get(), Some(&"bar"));
+}
+
+#[test]
+fn partialeq_impl() {
+ assert!(OnceCell::from("value") == OnceCell::from("value"));
+ assert!(OnceCell::from("foo") != OnceCell::from("bar"));
+
+ assert!(OnceCell::<String>::new() == OnceCell::new());
+ assert!(OnceCell::<String>::new() != OnceCell::from("value".to_owned()));
+}
+
+#[test]
+fn into_inner() {
+ 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()));
+}
+
+#[test]
+fn debug_impl() {
+ let cell = OnceCell::new();
+ assert_eq!(format!("{:#?}", cell), "OnceCell(Uninit)");
+ cell.set(vec!["hello", "world"]).unwrap();
+ assert_eq!(
+ format!("{:#?}", cell),
+ r#"OnceCell(
+ [
+ "hello",
+ "world",
+ ],
+)"#
+ );
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // miri doesn't support processes
+#[cfg(feature = "std")]
+fn reentrant_init() {
+ let examples_dir = {
+ let mut exe = std::env::current_exe().unwrap();
+ exe.pop();
+ exe.pop();
+ exe.push("examples");
+ exe
+ };
+ let bin = examples_dir
+ .join("reentrant_init_deadlocks")
+ .with_extension(std::env::consts::EXE_EXTENSION);
+ let mut guard = Guard { child: std::process::Command::new(bin).spawn().unwrap() };
+ std::thread::sleep(std::time::Duration::from_secs(2));
+ let status = guard.child.try_wait().unwrap();
+ assert!(status.is_none());
+
+ struct Guard {
+ child: std::process::Child,
+ }
+
+ impl Drop for Guard {
+ fn drop(&mut self) {
+ let _ = self.child.kill();
+ }
+ }
+}
+
+#[cfg(not(feature = "std"))]
+#[test]
+#[should_panic(expected = "reentrant init")]
+fn reentrant_init() {
+ let x: OnceCell<Box<i32>> = OnceCell::new();
+ let dangling_ref: Cell<Option<&i32>> = Cell::new(None);
+ x.get_or_init(|| {
+ let r = x.get_or_init(|| Box::new(92));
+ dangling_ref.set(Some(r));
+ Box::new(62)
+ });
+ eprintln!("use after free: {:?}", dangling_ref.get().unwrap());
+}
+
+#[test]
+fn eval_once_macro() {
+ macro_rules! eval_once {
+ (|| -> $ty:ty {
+ $($body:tt)*
+ }) => {{
+ static ONCE_CELL: OnceCell<$ty> = OnceCell::new();
+ fn init() -> $ty {
+ $($body)*
+ }
+ ONCE_CELL.get_or_init(init)
+ }};
+ }
+
+ let fib: &'static Vec<i32> = eval_once! {
+ || -> Vec<i32> {
+ let mut res = vec![1, 1];
+ for i in 0..10 {
+ let next = res[i] + res[i + 1];
+ res.push(next);
+ }
+ res
+ }
+ };
+ assert_eq!(fib[5], 8)
+}
+
+#[test]
+fn once_cell_does_not_leak_partially_constructed_boxes() {
+ let n_tries = if cfg!(miri) { 10 } else { 100 };
+ let n_readers = 10;
+ let n_writers = 3;
+ const MSG: &str = "Hello, World";
+
+ for _ in 0..n_tries {
+ let cell: OnceCell<String> = OnceCell::new();
+ scope(|scope| {
+ for _ in 0..n_readers {
+ scope.spawn(|| loop {
+ if let Some(msg) = cell.get() {
+ assert_eq!(msg, MSG);
+ break;
+ }
+ });
+ }
+ for _ in 0..n_writers {
+ let _ = scope.spawn(|| cell.set(MSG.to_owned()));
+ }
+ });
+ }
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn get_does_not_block() {
+ let cell = OnceCell::new();
+ let barrier = Barrier::new(2);
+ scope(|scope| {
+ scope.spawn(|| {
+ cell.get_or_init(|| {
+ barrier.wait();
+ barrier.wait();
+ "hello".to_string()
+ });
+ });
+ barrier.wait();
+ assert_eq!(cell.get(), None);
+ barrier.wait();
+ });
+ assert_eq!(cell.get(), Some(&"hello".to_string()));
+}
+
+#[test]
+// https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
+fn arrrrrrrrrrrrrrrrrrrrrr() {
+ let cell = OnceCell::new();
+ {
+ let s = String::new();
+ cell.set(&s).unwrap();
+ }
+}
+
+#[test]
+fn once_cell_is_sync_send() {
+ fn assert_traits<T: Send + Sync>() {}
+ assert_traits::<OnceCell<String>>();
+ assert_traits::<Lazy<String>>();
+}
diff --git a/vendor/once_cell/tests/it/unsync_lazy.rs b/vendor/once_cell/tests/it/unsync_lazy.rs
new file mode 100644
index 000000000..0c308cab0
--- /dev/null
+++ b/vendor/once_cell/tests/it/unsync_lazy.rs
@@ -0,0 +1,134 @@
+use core::{
+ cell::Cell,
+ sync::atomic::{AtomicUsize, Ordering::SeqCst},
+};
+
+use once_cell::unsync::Lazy;
+
+#[test]
+fn lazy_new() {
+ let called = Cell::new(0);
+ let x = Lazy::new(|| {
+ called.set(called.get() + 1);
+ 92
+ });
+
+ assert_eq!(called.get(), 0);
+
+ let y = *x - 30;
+ assert_eq!(y, 62);
+ assert_eq!(called.get(), 1);
+
+ let y = *x - 30;
+ assert_eq!(y, 62);
+ assert_eq!(called.get(), 1);
+}
+
+#[test]
+fn lazy_deref_mut() {
+ let called = Cell::new(0);
+ let mut x = Lazy::new(|| {
+ called.set(called.get() + 1);
+ 92
+ });
+
+ assert_eq!(called.get(), 0);
+
+ let y = *x - 30;
+ assert_eq!(y, 62);
+ assert_eq!(called.get(), 1);
+
+ *x /= 2;
+ assert_eq!(*x, 46);
+ assert_eq!(called.get(), 1);
+}
+
+#[test]
+fn lazy_force_mut() {
+ let called = Cell::new(0);
+ let mut x = Lazy::new(|| {
+ called.set(called.get() + 1);
+ 92
+ });
+ assert_eq!(called.get(), 0);
+ let v = Lazy::force_mut(&mut x);
+ assert_eq!(called.get(), 1);
+
+ *v /= 2;
+ assert_eq!(*x, 46);
+ assert_eq!(called.get(), 1);
+}
+
+#[test]
+fn lazy_get_mut() {
+ let called = Cell::new(0);
+ let mut x: Lazy<u32, _> = Lazy::new(|| {
+ called.set(called.get() + 1);
+ 92
+ });
+
+ assert_eq!(called.get(), 0);
+ assert_eq!(*x, 92);
+
+ let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap();
+ assert_eq!(called.get(), 1);
+
+ *mut_ref /= 2;
+ assert_eq!(*x, 46);
+ assert_eq!(called.get(), 1);
+}
+
+#[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<std::sync::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_into_value() {
+ let l: Lazy<i32, _> = Lazy::new(|| panic!());
+ assert!(matches!(Lazy::into_value(l), Err(_)));
+ let l = Lazy::new(|| -> i32 { 92 });
+ Lazy::force(&l);
+ assert!(matches!(Lazy::into_value(l), Ok(92)));
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn lazy_poisoning() {
+ let x: Lazy<String> = Lazy::new(|| panic!("kaboom"));
+ for _ in 0..2 {
+ let res = std::panic::catch_unwind(|| x.len());
+ assert!(res.is_err());
+ }
+}
+
+#[test]
+// https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
+fn arrrrrrrrrrrrrrrrrrrrrr() {
+ let lazy: Lazy<&String, _>;
+ {
+ let s = String::new();
+ lazy = Lazy::new(|| &s);
+ _ = *lazy;
+ }
+}
diff --git a/vendor/once_cell/tests/it/unsync_once_cell.rs b/vendor/once_cell/tests/it/unsync_once_cell.rs
new file mode 100644
index 000000000..124cc3e6d
--- /dev/null
+++ b/vendor/once_cell/tests/it/unsync_once_cell.rs
@@ -0,0 +1,154 @@
+use core::{
+ cell::Cell,
+ sync::atomic::{AtomicUsize, Ordering::SeqCst},
+};
+
+use once_cell::unsync::OnceCell;
+
+#[test]
+fn once_cell() {
+ let c = OnceCell::new();
+ assert!(c.get().is_none());
+ c.get_or_init(|| 92);
+ assert_eq!(c.get(), Some(&92));
+
+ c.get_or_init(|| panic!("Kabom!"));
+ assert_eq!(c.get(), Some(&92));
+}
+
+#[test]
+fn once_cell_with_value() {
+ const CELL: OnceCell<i32> = OnceCell::with_value(12);
+ let cell = CELL;
+ assert_eq!(cell.get(), Some(&12));
+}
+
+#[test]
+fn once_cell_get_mut() {
+ let mut c = OnceCell::new();
+ assert!(c.get_mut().is_none());
+ c.set(90).unwrap();
+ *c.get_mut().unwrap() += 2;
+ assert_eq!(c.get_mut(), Some(&mut 92));
+}
+
+#[test]
+fn once_cell_drop() {
+ static DROP_CNT: AtomicUsize = AtomicUsize::new(0);
+ struct Dropper;
+ impl Drop for Dropper {
+ fn drop(&mut self) {
+ DROP_CNT.fetch_add(1, SeqCst);
+ }
+ }
+
+ let x = OnceCell::new();
+ x.get_or_init(|| Dropper);
+ assert_eq!(DROP_CNT.load(SeqCst), 0);
+ drop(x);
+ assert_eq!(DROP_CNT.load(SeqCst), 1);
+}
+
+#[test]
+fn once_cell_drop_empty() {
+ let x = OnceCell::<String>::new();
+ drop(x);
+}
+
+#[test]
+fn clone() {
+ let s = OnceCell::new();
+ let c = s.clone();
+ assert!(c.get().is_none());
+
+ s.set("hello".to_string()).unwrap();
+ let c = s.clone();
+ assert_eq!(c.get().map(String::as_str), Some("hello"));
+}
+
+#[test]
+fn get_or_try_init() {
+ let cell: OnceCell<String> = OnceCell::new();
+ assert!(cell.get().is_none());
+
+ let res = std::panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() }));
+ assert!(res.is_err());
+ assert!(cell.get().is_none());
+
+ assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
+
+ assert_eq!(cell.get_or_try_init(|| Ok::<_, ()>("hello".to_string())), Ok(&"hello".to_string()));
+ assert_eq!(cell.get(), Some(&"hello".to_string()));
+}
+
+#[test]
+fn from_impl() {
+ assert_eq!(OnceCell::from("value").get(), Some(&"value"));
+ assert_ne!(OnceCell::from("foo").get(), Some(&"bar"));
+}
+
+#[test]
+fn partialeq_impl() {
+ assert!(OnceCell::from("value") == OnceCell::from("value"));
+ assert!(OnceCell::from("foo") != OnceCell::from("bar"));
+
+ assert!(OnceCell::<String>::new() == OnceCell::new());
+ assert!(OnceCell::<String>::new() != OnceCell::from("value".to_owned()));
+}
+
+#[test]
+fn into_inner() {
+ 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()));
+}
+
+#[test]
+fn debug_impl() {
+ let cell = OnceCell::new();
+ assert_eq!(format!("{:#?}", cell), "OnceCell(Uninit)");
+ cell.set(vec!["hello", "world"]).unwrap();
+ assert_eq!(
+ format!("{:#?}", cell),
+ r#"OnceCell(
+ [
+ "hello",
+ "world",
+ ],
+)"#
+ );
+}
+
+#[test]
+#[should_panic(expected = "reentrant init")]
+fn reentrant_init() {
+ let x: OnceCell<Box<i32>> = OnceCell::new();
+ let dangling_ref: Cell<Option<&i32>> = Cell::new(None);
+ x.get_or_init(|| {
+ let r = x.get_or_init(|| Box::new(92));
+ dangling_ref.set(Some(r));
+ Box::new(62)
+ });
+ eprintln!("use after free: {:?}", dangling_ref.get().unwrap());
+}
+
+#[test]
+fn aliasing_in_get() {
+ let x = OnceCell::new();
+ x.set(42).unwrap();
+ let at_x = x.get().unwrap(); // --- (shared) borrow of inner `Option<T>` --+
+ let _ = x.set(27); // <-- temporary (unique) borrow of inner `Option<T>` |
+ println!("{}", at_x); // <------- up until here ---------------------------+
+}
+
+#[test]
+// https://github.com/rust-lang/rust/issues/34761#issuecomment-256320669
+fn arrrrrrrrrrrrrrrrrrrrrr() {
+ let cell = OnceCell::new();
+ {
+ let s = String::new();
+ cell.set(&s).unwrap();
+ }
+}