diff options
| author | bors <bors@rust-lang.org> | 2017-02-03 03:23:35 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-02-03 03:23:35 +0000 |
| commit | 5de2a24b2ebfa42db8eadab911a107b4a67fabdb (patch) | |
| tree | 801d474d204637340ba30ed2521d68f2c9abdf63 /src/libcore | |
| parent | 7f294e4c186b461ee8fc28c75d4216822a535d7a (diff) | |
| parent | 8b947a37c8bf396cf80c3790f68253c97d435250 (diff) | |
| download | rust-5de2a24b2ebfa42db8eadab911a107b4a67fabdb.tar.gz rust-5de2a24b2ebfa42db8eadab911a107b4a67fabdb.zip | |
Auto merge of #39287 - wesleywiser:move_cell, r=aturon
Extend Cell to work with non-Copy types I'm not sure that I did this right but all of the tests pass. I also had to move the `new()` function so that `Cell`s with non-`Copy` `T`s could be created. That wasn't in the RFC but I assume it needed to be done?
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/cell.rs | 149 |
1 files changed, 108 insertions, 41 deletions
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index c3f862e7c54..ab44342ebf0 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -15,10 +15,18 @@ //! references. We say that `Cell<T>` and `RefCell<T>` provide 'interior mutability', in contrast //! with typical Rust types that exhibit 'inherited mutability'. //! -//! Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` provides `get` and `set` -//! methods that change the interior value with a single method call. `Cell<T>` though is only -//! compatible with types that implement `Copy`. For other types, one must use the `RefCell<T>` -//! type, acquiring a write lock before mutating. +//! Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` implements interior +//! mutability by moving values in and out of the `Cell<T>`. To use references instead of values, +//! one must use the `RefCell<T>` type, acquiring a write lock before mutating. `Cell<T>` provides +//! methods to retrieve and change the current interior value: +//! +//! - For types that implement `Copy`, the `get` method retrieves the current interior value. +//! - For types that implement `Default`, the `take` method replaces the current interior value +//! with `Default::default()` and returns the replaced value. +//! - For all types, the `replace` method replaces the current interior value and returns the +//! replaced value and the `into_inner` method consumes the `Cell<T>` and returns the interior +//! value. Additionally, the `set` method replaces the interior value, dropping the replaced +//! value. //! //! `RefCell<T>` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can //! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell<T>`s are @@ -176,9 +184,10 @@ 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. +/// A mutable memory location. /// /// See the [module-level documentation](index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] @@ -187,23 +196,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 +213,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 +351,100 @@ impl<T: Copy> From<T> for Cell<T> { } } +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); + /// ``` + #[unstable(feature = "move_cell", issue = "39264")] + 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); + /// ``` + #[unstable(feature = "move_cell", issue = "39264")] + pub fn into_inner(self) -> T { + unsafe { self.value.into_inner() } + } +} + +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); + /// ``` + #[unstable(feature = "move_cell", issue = "39264")] + 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> {} |
