From f121f094fe4d4f4e92142984e9230373c311e1e6 Mon Sep 17 00:00:00 2001
From: ThinkChaos <ThinkChaos@users.noreply.github.com>
Date: Tue, 21 Apr 2020 20:03:50 +0200
Subject: [PATCH 1/3] Add `RefCell::take`

In the same vein as `Cell::take` and `Option::take`.
---
 src/libcore/cell.rs | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index a922d4f118b5a..05c9c97a6126e 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -1023,6 +1023,27 @@ impl<T: ?Sized> RefCell<T> {
     }
 }
 
+impl<T: Default> RefCell<T> {
+    /// Takes the wrapped value, leaving `Default::default()` in its place.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(refcell_take)]
+    /// use std::cell::RefCell;
+    ///
+    /// let c = RefCell::new(5);
+    /// let five = c.take();
+    ///
+    /// assert_eq!(five, 5);
+    /// assert_eq!(c.into_inner(), 0);
+    /// ```
+    #[unstable(feature = "refcell_take", issue = "71395")]
+    pub fn take(&self) -> T {
+        self.replace(Default::default())
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl<T: ?Sized> Send for RefCell<T> where T: Send {}
 

From 4ea83bfb3d457770f2e54965dd86f672fbbc87c2 Mon Sep 17 00:00:00 2001
From: ThinkChaos <ThinkChaos@users.noreply.github.com>
Date: Tue, 21 Apr 2020 21:11:32 +0200
Subject: [PATCH 2/3] Use Cell::take in a couple places

---
 src/libstd/sync/once.rs                                         | 2 +-
 src/test/run-make/wasm-panic-small/foo.rs                       | 2 +-
 .../ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs   | 2 +-
 .../traits/negative-impls/pin-unsound-issue-66544-derefmut.rs   | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 1e6b6c430be90..a3ee14e85d222 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -497,7 +497,7 @@ impl Drop for WaiterQueue<'_> {
             let mut queue = (state_and_queue & !STATE_MASK) as *const Waiter;
             while !queue.is_null() {
                 let next = (*queue).next;
-                let thread = (*queue).thread.replace(None).unwrap();
+                let thread = (*queue).thread.take().unwrap();
                 (*queue).signaled.store(true, Ordering::Release);
                 // ^- FIXME (maybe): This is another case of issue #55005
                 // `store()` has a potentially dangling ref to `signaled`.
diff --git a/src/test/run-make/wasm-panic-small/foo.rs b/src/test/run-make/wasm-panic-small/foo.rs
index fd3dddb18eb20..6df52affe3993 100644
--- a/src/test/run-make/wasm-panic-small/foo.rs
+++ b/src/test/run-make/wasm-panic-small/foo.rs
@@ -23,5 +23,5 @@ pub fn foo() {
 pub fn foo() -> usize {
     use std::cell::Cell;
     thread_local!(static A: Cell<Vec<u32>> = Cell::new(Vec::new()));
-    A.try_with(|x| x.replace(Vec::new()).len()).unwrap_or(0)
+    A.try_with(|x| x.take().len()).unwrap_or(0)
 }
diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
index 499ac461e59a5..a5b85646581bf 100644
--- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
+++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-clone.rs
@@ -7,7 +7,7 @@ struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned);
 impl<'a> Clone for &'a mut MyType<'a> {
     //~^ ERROR E0751
     fn clone(&self) -> &'a mut MyType<'a> {
-        self.0.replace(None).unwrap()
+        self.0.take().unwrap()
     }
 }
 
diff --git a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
index 245be80078056..606cc65a84bc2 100644
--- a/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
+++ b/src/test/ui/traits/negative-impls/pin-unsound-issue-66544-derefmut.rs
@@ -12,7 +12,7 @@ struct MyType<'a>(Cell<Option<&'a mut MyType<'a>>>, PhantomPinned);
 impl<'a> DerefMut for &'a MyType<'a> {
     //~^ ERROR E0751
     fn deref_mut(&mut self) -> &mut MyType<'a> {
-        self.0.replace(None).unwrap()
+        self.0.take().unwrap()
     }
 }
 

From 4a79424b748338bd9635f0115c025942af2d5c3d Mon Sep 17 00:00:00 2001
From: ThinkChaos <ThinkChaos@users.noreply.github.com>
Date: Sun, 3 May 2020 12:52:23 +0200
Subject: [PATCH 3/3] Mention `RefCell::take` can panic in docs

---
 src/libcore/cell.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 05c9c97a6126e..0f2665eba6f22 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -1026,6 +1026,10 @@ impl<T: ?Sized> RefCell<T> {
 impl<T: Default> RefCell<T> {
     /// Takes the wrapped value, leaving `Default::default()` in its place.
     ///
+    /// # Panics
+    ///
+    /// Panics if the value is currently borrowed.
+    ///
     /// # Examples
     ///
     /// ```