Skip to content

Commit

Permalink
Extend Cell to work with non-Copy types
Browse files Browse the repository at this point in the history
  • Loading branch information
wesleywiser committed Jan 25, 2017
1 parent 83c2d95 commit c6cfa3c
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 36 deletions.
130 changes: 94 additions & 36 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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> {}

Expand Down
31 changes: 31 additions & 0 deletions src/libcoretest/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions src/libcoretest/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#![feature(ordering_chaining)]
#![feature(result_unwrap_or_default)]
#![feature(ptr_unaligned)]
#![feature(move_cell)]

extern crate core;
extern crate test;
Expand Down

0 comments on commit c6cfa3c

Please sign in to comment.