diff options
| author | Orson Peters <orsonpeters@gmail.com> | 2025-05-28 17:52:24 +0200 |
|---|---|---|
| committer | Orson Peters <orsonpeters@gmail.com> | 2025-05-28 17:53:14 +0200 |
| commit | 9ffbc62cb60f2151a38b6c5e18c016e406d10a62 (patch) | |
| tree | f5238d07e6c75b4d4cb0405ed8d94739f1c0794e | |
| parent | 8785f7b122bbb83d308035565f243ceb95ce4736 (diff) | |
| download | rust-9ffbc62cb60f2151a38b6c5e18c016e406d10a62.tar.gz rust-9ffbc62cb60f2151a38b6c5e18c016e406d10a62.zip | |
When replacing an old value we may not drop it in place
| -rw-r--r-- | library/std/src/sys/thread_local/native/lazy.rs | 20 |
1 files changed, 8 insertions, 12 deletions
diff --git a/library/std/src/sys/thread_local/native/lazy.rs b/library/std/src/sys/thread_local/native/lazy.rs index 2eb1c981edb..a2bf8d8b968 100644 --- a/library/std/src/sys/thread_local/native/lazy.rs +++ b/library/std/src/sys/thread_local/native/lazy.rs @@ -77,23 +77,19 @@ where let v = i.and_then(Option::take).unwrap_or_else(f); + // SAFETY: we cannot be inside a `LocalKey::with` scope, as the initializer + // has already returned and the next scope only starts after we return + // the pointer. Therefore, there can be no references to the old value, + // even if it was initialized. Thus because we are !Sync we have exclusive + // access to self.value and may replace it. + let mut old_value = unsafe { self.value.get().replace(MaybeUninit::new(v)) }; match self.state.replace(State::Alive) { State::Uninitialized => D::register_dtor(self), - - State::Alive => { - // An init occurred during a recursive call, this could be a panic in the future. - - // SAFETY: we cannot be inside a `LocalKey::with` scope, as the initializer - // has already returned and the next scope only starts after we return - // the pointer. Therefore, there can be no references to the old value. - unsafe { (*self.value.get()).assume_init_drop() } - } - + State::Alive => unsafe { old_value.assume_init_drop() }, State::Destroyed(_) => unreachable!(), } - // SAFETY: we are !Sync so we have exclusive access to self.value. - unsafe { (*self.value.get()).write(v) } + self.value.get().cast() } } |
