diff --git a/CHANGELOG.md b/CHANGELOG.md index bf489b2..152a72d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ - +## 1.17.2 + +- Avoid unnecessary synchronization in `Lazy::{force,deref}_mut()`, [#231](https://github.com/matklad/once_cell/pull/231). + ## 1.17.1 - Make `OnceRef` implementation compliant with [strict provenance](https://github.com/rust-lang/rust/issues/95228). diff --git a/Cargo.lock.msrv b/Cargo.lock.msrv index 6825f80..9edd508 100644 --- a/Cargo.lock.msrv +++ b/Cargo.lock.msrv @@ -45,7 +45,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "once_cell 1.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 1.14.0", ] [[package]] @@ -69,20 +69,21 @@ 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.2" dependencies = [ "atomic-polyfill", + "critical-section", "crossbeam-utils", "lazy_static", "parking_lot_core", "regex", ] -[[package]] -name = "once_cell" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" - [[package]] name = "parking_lot_core" version = "0.9.3" diff --git a/Cargo.toml b/Cargo.toml index ad02c34..46f9c32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "once_cell" -version = "1.17.1" +version = "1.17.2" authors = ["Aleksey Kladov "] license = "MIT OR Apache-2.0" edition = "2021" diff --git a/src/lib.rs b/src/lib.rs index 9239296..4c2d0e4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -796,8 +796,14 @@ pub mod unsync { /// assert_eq!(*lazy, 92); /// ``` pub fn force_mut(this: &mut Lazy) -> &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 @@ -844,8 +850,7 @@ pub mod unsync { impl T> DerefMut for Lazy { fn deref_mut(&mut self) -> &mut T { - Lazy::force(self); - self.cell.get_mut().unwrap_or_else(|| unreachable!()) + Lazy::force_mut(self) } } @@ -1324,8 +1329,14 @@ pub mod sync { /// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92); /// ``` pub fn force_mut(this: &mut Lazy) -> &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 @@ -1372,8 +1383,7 @@ pub mod sync { impl T> DerefMut for Lazy { fn deref_mut(&mut self) -> &mut T { - Lazy::force(self); - self.cell.get_mut().unwrap_or_else(|| unreachable!()) + Lazy::force_mut(self) } } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 9a26f0d..c4ac864 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -48,7 +48,21 @@ fn main() -> xshell::Result<()> { let _s = section("TEST_MSRV"); let _e = push_toolchain(&sh, MSRV)?; sh.copy_file("Cargo.lock.msrv", "Cargo.lock")?; - cmd!(sh, "cargo build").run()?; + if let err @ Err(_) = cmd!(sh, "cargo update -w -v --locked").run() { + // `Cargo.lock.msrv` is out of date! Probably from having bumped our own version number. + println! {"\ + Error: `Cargo.lock.msrv` is out of date. \ + Please run:\n \ + (cp Cargo.lock{{.msrv,}} && cargo +{MSRV} update -w -v && cp Cargo.lock{{.msrv,}})\n\ + \n\ + Alternatively, `git apply` the `.patch` below:\ + "} + cmd!(sh, "cargo update -q -w").quiet().run()?; + sh.copy_file("Cargo.lock", "Cargo.lock.msrv")?; + cmd!(sh, "git --no-pager diff --color=always -- Cargo.lock.msrv").quiet().run()?; + return err; + } + cmd!(sh, "cargo build --locked").run()?; } {