diff options
| author | Aleksey Kladov <aleksey.kladov@gmail.com> | 2020-08-17 23:54:41 +0200 |
|---|---|---|
| committer | Aleksey Kladov <aleksey.kladov@gmail.com> | 2020-08-18 00:34:54 +0200 |
| commit | 695d86f584bf2fb1fd49d34b83166b6b28d99d10 (patch) | |
| tree | 33148dc3aaf7e9a01a1d991aeb21ce746b4a256e | |
| parent | 33c96b4d9782cf6364e47cb2c904e66b06c22bb4 (diff) | |
| download | rust-695d86f584bf2fb1fd49d34b83166b6b28d99d10.tar.gz rust-695d86f584bf2fb1fd49d34b83166b6b28d99d10.zip | |
Make OnceCell<T> 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
| -rw-r--r-- | library/core/tests/lazy.rs | 9 | ||||
| -rw-r--r-- | 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<T> SyncOnceCell<T> { } } -impl<T> Drop for SyncOnceCell<T> { +unsafe impl<#[may_dangle] T> Drop for SyncOnceCell<T> { 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(); + } + } } |
