From 695d86f584bf2fb1fd49d34b83166b6b28d99d10 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 17 Aug 2020 23:54:41 +0200 Subject: [PATCH] Make OnceCell transparent to dropck See the failed build in https://github.com/rust-lang/rust/pull/75555#issuecomment-675016718 for an example where we need this in real life --- library/core/tests/lazy.rs | 9 +++++++++ library/std/src/lazy.rs | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs index 1c0bddb9aef..24f921ca7e4 100644 --- a/library/core/tests/lazy.rs +++ b/library/core/tests/lazy.rs @@ -122,3 +122,12 @@ fn reentrant_init() { }); eprintln!("use after free: {:?}", dangling_ref.get().unwrap()); } + +#[test] +fn dropck() { + let cell = OnceCell::new(); + { + let s = String::new(); + cell.set(&s).unwrap(); + } +} diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs index 60eba96bcc0..c1d05213e11 100644 --- a/library/std/src/lazy.rs +++ b/library/std/src/lazy.rs @@ -386,9 +386,10 @@ impl SyncOnceCell { } } -impl Drop for SyncOnceCell { +unsafe impl<#[may_dangle] T> Drop for SyncOnceCell { fn drop(&mut self) { - // Safety: The cell is being dropped, so it can't be accessed again + // Safety: The cell is being dropped, so it can't be accessed again. + // We also don't touch the `T`, which validates our usage of #[may_dangle]. unsafe { self.take_inner() }; } } @@ -845,4 +846,13 @@ mod tests { assert_eq!(msg, MSG); } } + + #[test] + fn dropck() { + let cell = SyncOnceCell::new(); + { + let s = String::new(); + cell.set(&s).unwrap(); + } + } }