Extend Cell to work with non-Copy types

Part of #39264
This commit is contained in:
Wesley Wiser 2017-01-24 22:44:33 -05:00
parent 83c2d95238
commit c6cfa3c489
3 changed files with 126 additions and 36 deletions

View File

@ -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> {}

View 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();

View 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;