about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2017-01-24 22:44:33 -0500
committerWesley Wiser <wwiser@gmail.com>2017-01-24 22:48:38 -0500
commitc6cfa3c4899e46addfe6d04d6aaa2d247056748f (patch)
tree2e27e883994bd4d8971196ac92939116aaab768a
parent83c2d95238e3545e7ae9af4873c48b1e3651c164 (diff)
downloadrust-c6cfa3c4899e46addfe6d04d6aaa2d247056748f.tar.gz
rust-c6cfa3c4899e46addfe6d04d6aaa2d247056748f.zip
Extend Cell to work with non-Copy types
Part of #39264
-rw-r--r--src/libcore/cell.rs130
-rw-r--r--src/libcoretest/cell.rs31
-rw-r--r--src/libcoretest/lib.rs1
3 files changed, 126 insertions, 36 deletions
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index c3f862e7c54..cafa19afcb6 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -176,6 +176,7 @@
 use cmp::Ordering;
 use fmt::{self, Debug, Display};
 use marker::Unsize;
+use mem;
 use ops::{Deref, DerefMut, CoerceUnsized};
 
 /// A mutable memory location that admits only `Copy` data.
@@ -187,23 +188,6 @@ pub struct Cell<T> {
 }
 
 impl<T:Copy> Cell<T> {
-    /// Creates a new `Cell` containing the given value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::cell::Cell;
-    ///
-    /// let c = Cell::new(5);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub const fn new(value: T) -> Cell<T> {
-        Cell {
-            value: UnsafeCell::new(value),
-        }
-    }
-
     /// Returns a copy of the contained value.
     ///
     /// # Examples
@@ -221,25 +205,6 @@ impl<T:Copy> Cell<T> {
         unsafe{ *self.value.get() }
     }
 
-    /// Sets the contained value.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::cell::Cell;
-    ///
-    /// let c = Cell::new(5);
-    ///
-    /// c.set(10);
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn set(&self, value: T) {
-        unsafe {
-            *self.value.get() = value;
-        }
-    }
-
     /// Returns a reference to the underlying `UnsafeCell`.
     ///
     /// # Examples
@@ -378,6 +343,99 @@ impl<T: Copy> From<T> for Cell<T> {
     }
 }
 
+#[unstable(feature = "move_cell", issue = "39264")]
+impl<T> Cell<T> {
+    /// Creates a new `Cell` containing the given value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::cell::Cell;
+    ///
+    /// let c = Cell::new(5);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[inline]
+    pub const fn new(value: T) -> Cell<T> {
+        Cell {
+            value: UnsafeCell::new(value),
+        }
+    }
+
+    /// Sets the contained value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::cell::Cell;
+    ///
+    /// let c = Cell::new(5);
+    ///
+    /// c.set(10);
+    /// ```
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn set(&self, val: T) {
+        let old = self.replace(val);
+        drop(old);
+    }
+
+    /// Replaces the contained value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(move_cell)]
+    /// use std::cell::Cell;
+    ///
+    /// let c = Cell::new(5);
+    /// let old = c.replace(10);
+    ///
+    /// assert_eq!(5, old);
+    /// ```
+    pub fn replace(&self, val: T) -> T {
+        mem::replace(unsafe { &mut *self.value.get() }, val)
+    }
+
+    /// Unwraps the value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(move_cell)]
+    /// use std::cell::Cell;
+    ///
+    /// let c = Cell::new(5);
+    /// let five = c.into_inner();
+    ///
+    /// assert_eq!(five, 5);
+    /// ```
+    pub fn into_inner(self) -> T {
+        unsafe { self.value.into_inner() }
+    }
+}
+
+#[unstable(feature = "move_cell", issue = "39264")]
+impl<T: Default> Cell<T> {
+    /// Takes the value of the cell, leaving `Default::default()` in its place.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(move_cell)]
+    /// use std::cell::Cell;
+    ///
+    /// let c = Cell::new(5);
+    /// let five = c.take();
+    ///
+    /// assert_eq!(five, 5);
+    /// assert_eq!(c.into_inner(), 0);
+    /// ```
+    pub fn take(&self) -> T {
+        self.replace(Default::default())
+    }
+}
+
 #[unstable(feature = "coerce_unsized", issue = "27732")]
 impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {}
 
diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs
index 724a312ea79..8585f2f0871 100644
--- a/src/libcoretest/cell.rs
+++ b/src/libcoretest/cell.rs
@@ -210,6 +210,37 @@ fn cell_default() {
 }
 
 #[test]
+fn cell_set() {
+    let cell = Cell::new(10);
+    cell.set(20);
+    assert_eq!(20, cell.get());
+
+    let cell = Cell::new("Hello".to_owned());
+    cell.set("World".to_owned());
+    assert_eq!("World".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn cell_replace() {
+    let cell = Cell::new(10);
+    assert_eq!(10, cell.replace(20));
+    assert_eq!(20, cell.get());
+
+    let cell = Cell::new("Hello".to_owned());
+    assert_eq!("Hello".to_owned(), cell.replace("World".to_owned()));
+    assert_eq!("World".to_owned(), cell.into_inner());
+}
+
+#[test]
+fn cell_into_inner() {
+    let cell = Cell::new(10);
+    assert_eq!(10, cell.into_inner());
+
+    let cell = Cell::new("Hello world".to_owned());
+    assert_eq!("Hello world".to_owned(), cell.into_inner());
+}
+
+#[test]
 fn refcell_default() {
     let cell: RefCell<u64> = Default::default();
     assert_eq!(0, *cell.borrow());
diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs
index ee47b510ee0..ea88d45630c 100644
--- a/src/libcoretest/lib.rs
+++ b/src/libcoretest/lib.rs
@@ -34,6 +34,7 @@
 #![feature(ordering_chaining)]
 #![feature(result_unwrap_or_default)]
 #![feature(ptr_unaligned)]
+#![feature(move_cell)]
 
 extern crate core;
 extern crate test;