]> git.lizzy.rs Git - rust.git/commitdiff
Extend Cell to work with non-Copy types
authorWesley Wiser <wwiser@gmail.com>
Wed, 25 Jan 2017 03:44:33 +0000 (22:44 -0500)
committerWesley Wiser <wwiser@gmail.com>
Wed, 25 Jan 2017 03:48:38 +0000 (22:48 -0500)
Part of #39264

src/libcore/cell.rs
src/libcoretest/cell.rs
src/libcoretest/lib.rs

index c3f862e7c5418b5a8bb4d14ffe1a02fc87c9492f..cafa19afcb6489f2f884a693c9d83050592ab840 100644 (file)
 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 @@ pub fn get(&self) -> 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 @@ fn from(t: T) -> 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> {}
 
index 724a312ea79e0a7427df2856805485c8cc146802..8585f2f08711332a3e5af0fa53145df9e1b657ec 100644 (file)
@@ -209,6 +209,37 @@ fn cell_default() {
     assert_eq!(0, cell.get());
 }
 
+#[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();
index ee47b510ee0744fef35629d023734c4782a78c7a..ea88d45630c46e77c5473619718f2c3415ae9e0e 100644 (file)
@@ -34,6 +34,7 @@
 #![feature(ordering_chaining)]
 #![feature(result_unwrap_or_default)]
 #![feature(ptr_unaligned)]
+#![feature(move_cell)]
 
 extern crate core;
 extern crate test;