Skip to content

Commit c6cfa3c

Browse files
committed
Extend Cell to work with non-Copy types
Part of #39264
1 parent 83c2d95 commit c6cfa3c

File tree

3 files changed

+126
-36
lines changed

3 files changed

+126
-36
lines changed

src/libcore/cell.rs

Lines changed: 94 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@
176176
use cmp::Ordering;
177177
use fmt::{self, Debug, Display};
178178
use marker::Unsize;
179+
use mem;
179180
use ops::{Deref, DerefMut, CoerceUnsized};
180181

181182
/// A mutable memory location that admits only `Copy` data.
@@ -187,23 +188,6 @@ pub struct Cell<T> {
187188
}
188189

189190
impl<T:Copy> Cell<T> {
190-
/// Creates a new `Cell` containing the given value.
191-
///
192-
/// # Examples
193-
///
194-
/// ```
195-
/// use std::cell::Cell;
196-
///
197-
/// let c = Cell::new(5);
198-
/// ```
199-
#[stable(feature = "rust1", since = "1.0.0")]
200-
#[inline]
201-
pub const fn new(value: T) -> Cell<T> {
202-
Cell {
203-
value: UnsafeCell::new(value),
204-
}
205-
}
206-
207191
/// Returns a copy of the contained value.
208192
///
209193
/// # Examples
@@ -221,25 +205,6 @@ impl<T:Copy> Cell<T> {
221205
unsafe{ *self.value.get() }
222206
}
223207

224-
/// Sets the contained value.
225-
///
226-
/// # Examples
227-
///
228-
/// ```
229-
/// use std::cell::Cell;
230-
///
231-
/// let c = Cell::new(5);
232-
///
233-
/// c.set(10);
234-
/// ```
235-
#[inline]
236-
#[stable(feature = "rust1", since = "1.0.0")]
237-
pub fn set(&self, value: T) {
238-
unsafe {
239-
*self.value.get() = value;
240-
}
241-
}
242-
243208
/// Returns a reference to the underlying `UnsafeCell`.
244209
///
245210
/// # Examples
@@ -378,6 +343,99 @@ impl<T: Copy> From<T> for Cell<T> {
378343
}
379344
}
380345

346+
#[unstable(feature = "move_cell", issue = "39264")]
347+
impl<T> Cell<T> {
348+
/// Creates a new `Cell` containing the given value.
349+
///
350+
/// # Examples
351+
///
352+
/// ```
353+
/// use std::cell::Cell;
354+
///
355+
/// let c = Cell::new(5);
356+
/// ```
357+
#[stable(feature = "rust1", since = "1.0.0")]
358+
#[inline]
359+
pub const fn new(value: T) -> Cell<T> {
360+
Cell {
361+
value: UnsafeCell::new(value),
362+
}
363+
}
364+
365+
/// Sets the contained value.
366+
///
367+
/// # Examples
368+
///
369+
/// ```
370+
/// use std::cell::Cell;
371+
///
372+
/// let c = Cell::new(5);
373+
///
374+
/// c.set(10);
375+
/// ```
376+
#[inline]
377+
#[stable(feature = "rust1", since = "1.0.0")]
378+
pub fn set(&self, val: T) {
379+
let old = self.replace(val);
380+
drop(old);
381+
}
382+
383+
/// Replaces the contained value.
384+
///
385+
/// # Examples
386+
///
387+
/// ```
388+
/// #![feature(move_cell)]
389+
/// use std::cell::Cell;
390+
///
391+
/// let c = Cell::new(5);
392+
/// let old = c.replace(10);
393+
///
394+
/// assert_eq!(5, old);
395+
/// ```
396+
pub fn replace(&self, val: T) -> T {
397+
mem::replace(unsafe { &mut *self.value.get() }, val)
398+
}
399+
400+
/// Unwraps the value.
401+
///
402+
/// # Examples
403+
///
404+
/// ```
405+
/// #![feature(move_cell)]
406+
/// use std::cell::Cell;
407+
///
408+
/// let c = Cell::new(5);
409+
/// let five = c.into_inner();
410+
///
411+
/// assert_eq!(five, 5);
412+
/// ```
413+
pub fn into_inner(self) -> T {
414+
unsafe { self.value.into_inner() }
415+
}
416+
}
417+
418+
#[unstable(feature = "move_cell", issue = "39264")]
419+
impl<T: Default> Cell<T> {
420+
/// Takes the value of the cell, leaving `Default::default()` in its place.
421+
///
422+
/// # Examples
423+
///
424+
/// ```
425+
/// #![feature(move_cell)]
426+
/// use std::cell::Cell;
427+
///
428+
/// let c = Cell::new(5);
429+
/// let five = c.take();
430+
///
431+
/// assert_eq!(five, 5);
432+
/// assert_eq!(c.into_inner(), 0);
433+
/// ```
434+
pub fn take(&self) -> T {
435+
self.replace(Default::default())
436+
}
437+
}
438+
381439
#[unstable(feature = "coerce_unsized", issue = "27732")]
382440
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {}
383441

src/libcoretest/cell.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,37 @@ fn cell_default() {
209209
assert_eq!(0, cell.get());
210210
}
211211

212+
#[test]
213+
fn cell_set() {
214+
let cell = Cell::new(10);
215+
cell.set(20);
216+
assert_eq!(20, cell.get());
217+
218+
let cell = Cell::new("Hello".to_owned());
219+
cell.set("World".to_owned());
220+
assert_eq!("World".to_owned(), cell.into_inner());
221+
}
222+
223+
#[test]
224+
fn cell_replace() {
225+
let cell = Cell::new(10);
226+
assert_eq!(10, cell.replace(20));
227+
assert_eq!(20, cell.get());
228+
229+
let cell = Cell::new("Hello".to_owned());
230+
assert_eq!("Hello".to_owned(), cell.replace("World".to_owned()));
231+
assert_eq!("World".to_owned(), cell.into_inner());
232+
}
233+
234+
#[test]
235+
fn cell_into_inner() {
236+
let cell = Cell::new(10);
237+
assert_eq!(10, cell.into_inner());
238+
239+
let cell = Cell::new("Hello world".to_owned());
240+
assert_eq!("Hello world".to_owned(), cell.into_inner());
241+
}
242+
212243
#[test]
213244
fn refcell_default() {
214245
let cell: RefCell<u64> = Default::default();

src/libcoretest/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#![feature(ordering_chaining)]
3535
#![feature(result_unwrap_or_default)]
3636
#![feature(ptr_unaligned)]
37+
#![feature(move_cell)]
3738

3839
extern crate core;
3940
extern crate test;

0 commit comments

Comments
 (0)