diff options
| author | F001 <changchun.fan@qq.com> | 2018-05-07 15:24:45 +0800 |
|---|---|---|
| committer | F001 <changchun.fan@qq.com> | 2018-07-17 11:34:19 +0800 |
| commit | 9928baa786f645a22072fd2fb4b68173eced61f9 (patch) | |
| tree | 7c64b98bc9012b37248b23f2f8ffd83df61ad1ad | |
| parent | 55c04babb88beb20331b80ad9e4a51f860fb2392 (diff) | |
| download | rust-9928baa786f645a22072fd2fb4b68173eced61f9.tar.gz rust-9928baa786f645a22072fd2fb4b68173eced61f9.zip | |
implement rfc 1789
| -rw-r--r-- | src/libcore/cell.rs | 147 | ||||
| -rw-r--r-- | src/test/run-pass/rfc-1789-as-cell/from-mut.rs | 22 |
2 files changed, 125 insertions, 44 deletions
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 2292617f51e..3536588f9df 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -200,8 +200,9 @@ use cmp::Ordering; use fmt::{self, Debug, Display}; use marker::Unsize; use mem; -use ops::{Deref, DerefMut, CoerceUnsized}; +use ops::{Deref, DerefMut, CoerceUnsized, Index}; use ptr; +use slice::SliceIndex; /// A mutable memory location. /// @@ -236,7 +237,7 @@ use ptr; /// See the [module-level documentation](index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] -pub struct Cell<T> { +pub struct Cell<T: ?Sized> { value: UnsafeCell<T>, } @@ -287,10 +288,10 @@ impl<T:Copy> Cell<T> { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<T> Send for Cell<T> where T: Send {} +unsafe impl<T: ?Sized> Send for Cell<T> where T: Send {} #[stable(feature = "rust1", since = "1.0.0")] -impl<T> !Sync for Cell<T> {} +impl<T: ?Sized> !Sync for Cell<T> {} #[stable(feature = "rust1", since = "1.0.0")] impl<T:Copy> Clone for Cell<T> { @@ -381,46 +382,6 @@ impl<T> Cell<T> { } } - /// Returns a raw pointer to the underlying data in this cell. - /// - /// # Examples - /// - /// ``` - /// use std::cell::Cell; - /// - /// let c = Cell::new(5); - /// - /// let ptr = c.as_ptr(); - /// ``` - #[inline] - #[stable(feature = "cell_as_ptr", since = "1.12.0")] - pub fn as_ptr(&self) -> *mut T { - self.value.get() - } - - /// Returns a mutable reference to the underlying data. - /// - /// This call borrows `Cell` mutably (at compile-time) which guarantees - /// that we possess the only reference. - /// - /// # Examples - /// - /// ``` - /// use std::cell::Cell; - /// - /// let mut c = Cell::new(5); - /// *c.get_mut() += 1; - /// - /// assert_eq!(c.get(), 6); - /// ``` - #[inline] - #[stable(feature = "cell_get_mut", since = "1.11.0")] - pub fn get_mut(&mut self) -> &mut T { - unsafe { - &mut *self.value.get() - } - } - /// Sets the contained value. /// /// # Examples @@ -499,6 +460,90 @@ impl<T> Cell<T> { } } +impl<T: ?Sized> Cell<T> { + /// Returns a raw pointer to the underlying data in this cell. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let ptr = c.as_ptr(); + /// ``` + #[inline] + #[stable(feature = "cell_as_ptr", since = "1.12.0")] + pub fn as_ptr(&self) -> *mut T { + self.value.get() + } + + /// Returns a mutable reference to the underlying data. + /// + /// This call borrows `Cell` mutably (at compile-time) which guarantees + /// that we possess the only reference. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let mut c = Cell::new(5); + /// *c.get_mut() += 1; + /// + /// assert_eq!(c.get(), 6); + /// ``` + #[inline] + #[stable(feature = "cell_get_mut", since = "1.11.0")] + pub fn get_mut(&mut self) -> &mut T { + unsafe { + &mut *self.value.get() + } + } + + /// Returns a `&Cell<T>` from a `&mut T` + /// + /// # Examples + /// + /// ``` + /// #![feature(as_cell)] + /// use std::cell::Cell; + /// let slice: &mut [i32] = &mut [1,2,3]; + /// let cell_slice: &Cell<[i32]> = Cell::from_mut(slice); + /// + /// assert_eq!(cell_slice.get_with(|v|v.len()), 3) + /// ``` + #[inline] + #[unstable(feature = "as_cell", issue="43038")] + pub fn from_mut<'a>(t: &'a mut T) -> &'a Cell<T> { + unsafe { + &*(t as *mut T as *const Cell<T>) + } + } + + /// Returns a value by applying a function on contained value + /// + /// # Examples + /// + /// ``` + /// #![feature(as_cell)] + /// use std::cell::Cell; + /// let c : Cell<Vec<i32>> = Cell::new(vec![1,2,3]); + /// let sum : i32 = c.get_with(|v|v.iter().sum()); + /// assert_eq!(sum, 6_i32); + /// ``` + #[inline] + #[unstable(feature = "as_cell", issue="43038")] + pub fn get_with<U, F>(&self, f: F) -> U + where + F: Fn(&T) -> U, U: 'static + { + unsafe { + f(&*self.value.get()) + } + } +} + impl<T: Default> Cell<T> { /// Takes the value of the cell, leaving `Default::default()` in its place. /// @@ -522,6 +567,20 @@ impl<T: Default> Cell<T> { #[unstable(feature = "coerce_unsized", issue = "27732")] impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {} +#[unstable(feature = "as_cell", issue="43038")] +impl<T, I> Index<I> for Cell<[T]> +where + I: SliceIndex<[Cell<T>]> +{ + type Output = I::Output; + + fn index(&self, index: I) -> &Self::Output { + unsafe { + Index::index(&*(self as *const Cell<[T]> as *const [Cell<T>]), index) + } + } +} + /// A mutable memory location with dynamically checked borrow rules /// /// See the [module-level documentation](index.html) for more. diff --git a/src/test/run-pass/rfc-1789-as-cell/from-mut.rs b/src/test/run-pass/rfc-1789-as-cell/from-mut.rs new file mode 100644 index 00000000000..33257124f57 --- /dev/null +++ b/src/test/run-pass/rfc-1789-as-cell/from-mut.rs @@ -0,0 +1,22 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(as_cell)] + +use std::cell::Cell; + +fn main() { + let slice: &mut [i32] = &mut [1,2,3]; + let cell_slice: &Cell<[i32]> = Cell::from_mut(slice); + assert_eq!(cell_slice.get_with(|v|v.len()), 3); + + let sub_slice : &[Cell<i32>] = &cell_slice[1..]; + assert_eq!(sub_slice.len(), 2); +} |
