From c6cfa3c4899e46addfe6d04d6aaa2d247056748f Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 24 Jan 2017 22:44:33 -0500 Subject: [PATCH] Extend Cell to work with non-Copy types Part of #39264 --- src/libcore/cell.rs | 130 +++++++++++++++++++++++++++++----------- src/libcoretest/cell.rs | 31 ++++++++++ src/libcoretest/lib.rs | 1 + 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 { } impl Cell { - /// 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 { - Cell { - value: UnsafeCell::new(value), - } - } - /// Returns a copy of the contained value. /// /// # Examples @@ -221,25 +205,6 @@ impl Cell { 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 From for Cell { } } +#[unstable(feature = "move_cell", issue = "39264")] +impl Cell { + /// 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 { + 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 Cell { + /// 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, U> CoerceUnsized> for Cell {} 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 @@ -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 = Default::default(); 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;