about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-09-06 10:29:54 +0000
committerbors <bors@rust-lang.org>2020-09-06 10:29:54 +0000
commit23e49ddafbe6765d117d3c7e2485d7ac73d9d79e (patch)
tree8506d047a9fd1a8b6acd44871ff278adf9dc33e5
parent6c6003a7ad5e1f03c7c458003bf469d267df5688 (diff)
parente56ea68db50d23f4a7efa712c53ba02e506fd61a (diff)
downloadrust-23e49ddafbe6765d117d3c7e2485d7ac73d9d79e.tar.gz
rust-23e49ddafbe6765d117d3c7e2485d7ac73d9d79e.zip
Auto merge of #76370 - fusion-engineering-forks:synconcecell-soundness, r=nagisa
Fix dropck issue of SyncOnceCell.

Fixes #76367.
-rw-r--r--library/std/src/lazy.rs27
1 files changed, 26 insertions, 1 deletions
diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs
index 845e9d76a77..d171231b0f1 100644
--- a/library/std/src/lazy.rs
+++ b/library/std/src/lazy.rs
@@ -6,6 +6,7 @@ mod tests;
 use crate::{
     cell::{Cell, UnsafeCell},
     fmt,
+    marker::PhantomData,
     mem::{self, MaybeUninit},
     ops::{Deref, Drop},
     panic::{RefUnwindSafe, UnwindSafe},
@@ -46,6 +47,26 @@ pub struct SyncOnceCell<T> {
     once: Once,
     // Whether or not the value is initialized is tracked by `state_and_queue`.
     value: UnsafeCell<MaybeUninit<T>>,
+    /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.
+    ///
+    /// ```compile_fail,E0597
+    /// #![feature(once_cell)]
+    ///
+    /// use std::lazy::SyncOnceCell;
+    ///
+    /// struct A<'a>(&'a str);
+    ///
+    /// impl<'a> Drop for A<'a> {
+    ///     fn drop(&mut self) {}
+    /// }
+    ///
+    /// let cell = SyncOnceCell::new();
+    /// {
+    ///     let s = String::new();
+    ///     let _ = cell.set(A(&s));
+    /// }
+    /// ```
+    _marker: PhantomData<T>,
 }
 
 // Why do we need `T: Send`?
@@ -119,7 +140,11 @@ impl<T> SyncOnceCell<T> {
     /// Creates a new empty cell.
     #[unstable(feature = "once_cell", issue = "74465")]
     pub const fn new() -> SyncOnceCell<T> {
-        SyncOnceCell { once: Once::new(), value: UnsafeCell::new(MaybeUninit::uninit()) }
+        SyncOnceCell {
+            once: Once::new(),
+            value: UnsafeCell::new(MaybeUninit::uninit()),
+            _marker: PhantomData,
+        }
     }
 
     /// Gets the reference to the underlying value.