diff options
| author | Without Boats <boats@mozilla.com> | 2018-09-01 06:12:10 +0200 |
|---|---|---|
| committer | Without Boats <boats@mozilla.com> | 2018-09-01 06:57:58 +0200 |
| commit | 974bdc80fe3214159dc30e0bbb76694900e613c0 (patch) | |
| tree | a4ce3c775b9c740ffffb0d7609fe14520fe1ec94 /src/liballoc | |
| parent | e6b35b0e1115f008796e8313574e4a4739b6d39d (diff) | |
| download | rust-974bdc80fe3214159dc30e0bbb76694900e613c0.tar.gz rust-974bdc80fe3214159dc30e0bbb76694900e613c0.zip | |
Update to a new pinning API.
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/boxed.rs | 38 | ||||
| -rw-r--r-- | src/liballoc/lib.rs | 1 | ||||
| -rw-r--r-- | src/liballoc/pin.rs | 302 | ||||
| -rw-r--r-- | src/liballoc/rc.rs | 6 | ||||
| -rw-r--r-- | src/liballoc/sync.rs | 6 |
5 files changed, 40 insertions, 313 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c25f3eb8f17..fce6417186f 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -65,13 +65,12 @@ use core::hash::{Hash, Hasher}; use core::iter::FusedIterator; use core::marker::{Unpin, Unsize}; use core::mem; -use core::pin::PinMut; +use core::pin::Pin; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll, Spawn, SpawnErrorKind, SpawnObjError}; use raw_vec::RawVec; -use pin::PinBox; use str::from_boxed_utf8_unchecked; /// A pointer type for heap allocation. @@ -97,6 +96,11 @@ impl<T> Box<T> { pub fn new(x: T) -> Box<T> { box x } + + #[unstable(feature = "pin", issue = "49150")] + pub fn pinned(x: T) -> Pin<Box<T>> { + unsafe { Pin::new_unchecked(box x) } + } } impl<T: ?Sized> Box<T> { @@ -427,6 +431,13 @@ impl<T> From<T> for Box<T> { } } +#[unstable(feature = "pin", issue = "49150")] +impl<T> From<Box<T>> for Pin<Box<T>> { + fn from(boxed: Box<T>) -> Self { + unsafe { Pin::new_unchecked(boxed) } + } +} + #[stable(feature = "box_from_slice", since = "1.17.0")] impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { fn from(slice: &'a [T]) -> Box<[T]> { @@ -764,8 +775,8 @@ impl<T> Generator for Box<T> impl<F: ?Sized + Future + Unpin> Future for Box<F> { type Output = F::Output; - fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> { - PinMut::new(&mut **self).poll(cx) + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { + F::poll(Pin::new(&mut *self), cx) } } @@ -779,8 +790,8 @@ unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F> unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> { let ptr = ptr as *mut F; - let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr); - pin.poll(cx) + let pin: Pin<&mut F> = Pin::new_unchecked(&mut *ptr); + F::poll(pin, cx) } unsafe fn drop(ptr: *mut ()) { @@ -818,9 +829,16 @@ impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> { } } -#[unstable(feature = "pin", issue = "49150")] -impl<T: Unpin + ?Sized> From<PinBox<T>> for Box<T> { - fn from(pinned: PinBox<T>) -> Box<T> { - unsafe { PinBox::unpin(pinned) } +#[unstable(feature = "futures_api", issue = "50547")] +impl<'a, F: Future<Output = ()> + Send + 'a> From<Pin<Box<F>>> for FutureObj<'a, ()> { + fn from(boxed: Pin<Box<F>>) -> Self { + FutureObj::new(boxed) + } +} + +#[unstable(feature = "futures_api", issue = "50547")] +impl<'a, F: Future<Output = ()> + 'a> From<Pin<Box<F>>> for LocalFutureObj<'a, ()> { + fn from(boxed: Pin<Box<F>>) -> Self { + LocalFutureObj::new(boxed) } } diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 676c977514f..18d8cd773eb 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -160,7 +160,6 @@ pub mod collections; pub mod sync; pub mod rc; pub mod raw_vec; -pub mod pin; pub mod prelude; pub mod borrow; pub mod fmt; diff --git a/src/liballoc/pin.rs b/src/liballoc/pin.rs deleted file mode 100644 index 17bbc9882d9..00000000000 --- a/src/liballoc/pin.rs +++ /dev/null @@ -1,302 +0,0 @@ -//! Types which pin data to its location in memory -//! -//! It is sometimes useful to have objects that are guaranteed to not move, -//! in the sense that their placement in memory does not change, and can thus be relied upon. -//! -//! A prime example of such a scenario would be building self-referencial structs, -//! since moving an object with pointers to itself will invalidate them, -//! which could cause undefined behavior. -//! -//! In order to prevent objects from moving, they must be *pinned*, -//! by wrapping the data in pinning pointer types, such as [`PinMut`] and [`PinBox`], -//! which are otherwise equivalent to `& mut` and [`Box`], respectively. -//! -//! First of all, these are pointer types because pinned data mustn't be passed around by value -//! (that would change its location in memory). -//! Secondly, since data can be moved out of `&mut` and [`Box`] with functions such as [`swap`], -//! which causes their contents to swap places in memory, -//! we need dedicated types that prohibit such operations. -//! -//! However, these restrictions are usually not necessary, -//! so most types implement the [`Unpin`] auto-trait, -//! which indicates that the type can be moved out safely. -//! Doing so removes the limitations of pinning types, -//! making them the same as their non-pinning counterparts. -//! -//! [`PinMut`]: struct.PinMut.html -//! [`PinBox`]: struct.PinBox.html -//! [`Unpin`]: trait.Unpin.html -//! [`swap`]: ../../std/mem/fn.swap.html -//! [`Box`]: ../boxed/struct.Box.html -//! -//! # Examples -//! -//! ```rust -//! #![feature(pin)] -//! -//! use std::pin::PinBox; -//! use std::marker::Pinned; -//! use std::ptr::NonNull; -//! -//! // This is a self referencial struct since the slice field points to the data field. -//! // We cannot inform the compiler about that with a normal reference, -//! // since this pattern cannot be described with the usual borrowing rules. -//! // Instead we use a raw pointer, though one which is known to not be null, -//! // since we know it's pointing at the string. -//! struct Unmovable { -//! data: String, -//! slice: NonNull<String>, -//! _pin: Pinned, -//! } -//! -//! impl Unmovable { -//! // To ensure the data doesn't move when the function returns, -//! // we place it in the heap where it will stay for the lifetime of the object, -//! // and the only way to access it would be through a pointer to it. -//! fn new(data: String) -> PinBox<Self> { -//! let res = Unmovable { -//! data, -//! // we only create the pointer once the data is in place -//! // otherwise it will have already moved before we even started -//! slice: NonNull::dangling(), -//! _pin: Pinned, -//! }; -//! let mut boxed = PinBox::new(res); -//! -//! let slice = NonNull::from(&boxed.data); -//! // we know this is safe because modifying a field doesn't move the whole struct -//! unsafe { PinBox::get_mut(&mut boxed).slice = slice }; -//! boxed -//! } -//! } -//! -//! let unmoved = Unmovable::new("hello".to_string()); -//! // The pointer should point to the correct location, -//! // so long as the struct hasn't moved. -//! // Meanwhile, we are free to move the pointer around. -//! # #[allow(unused_mut)] -//! let mut still_unmoved = unmoved; -//! assert_eq!(still_unmoved.slice, NonNull::from(&still_unmoved.data)); -//! -//! // Since our type doesn't implement Unpin, this will fail to compile: -//! // let new_unmoved = Unmovable::new("world".to_string()); -//! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); -//! ``` - -#![unstable(feature = "pin", issue = "49150")] - -pub use core::pin::*; -pub use core::marker::Unpin; - -use core::convert::From; -use core::fmt; -use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj}; -use core::marker::Unsize; -use core::ops::{CoerceUnsized, Deref, DerefMut}; -use core::task::{Context, Poll}; - -use boxed::Box; - -/// A pinned, heap allocated reference. -/// -/// This type is similar to [`Box`], except that it pins its value, -/// which prevents it from moving out of the reference, unless it implements [`Unpin`]. -/// -/// See the [module documentation] for furthur explaination on pinning. -/// -/// [`Box`]: ../boxed/struct.Box.html -/// [`Unpin`]: ../../std/marker/trait.Unpin.html -/// [module documentation]: index.html -#[unstable(feature = "pin", issue = "49150")] -#[fundamental] -#[repr(transparent)] -pub struct PinBox<T: ?Sized> { - inner: Box<T>, -} - -#[unstable(feature = "pin", issue = "49150")] -impl<T> PinBox<T> { - /// Allocate memory on the heap, move the data into it and pin it. - #[unstable(feature = "pin", issue = "49150")] - pub fn new(data: T) -> PinBox<T> { - PinBox { inner: Box::new(data) } - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<T: ?Sized> PinBox<T> { - /// Get a pinned reference to the data in this PinBox. - #[inline] - pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> { - unsafe { PinMut::new_unchecked(&mut *self.inner) } - } - - /// Constructs a `PinBox` from a raw pointer. - /// - /// After calling this function, the raw pointer is owned by the - /// resulting `PinBox`. Specifically, the `PinBox` destructor will call - /// the destructor of `T` and free the allocated memory. Since the - /// way `PinBox` allocates and releases memory is unspecified, the - /// only valid pointer to pass to this function is the one taken - /// from another `PinBox` via the [`PinBox::into_raw`] function. - /// - /// This function is unsafe because improper use may lead to - /// memory problems. For example, a double-free may occur if the - /// function is called twice on the same raw pointer. - /// - /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw - /// - /// # Examples - /// - /// ``` - /// #![feature(pin)] - /// use std::pin::PinBox; - /// let x = PinBox::new(5); - /// let ptr = PinBox::into_raw(x); - /// let x = unsafe { PinBox::from_raw(ptr) }; - /// ``` - #[inline] - pub unsafe fn from_raw(raw: *mut T) -> Self { - PinBox { inner: Box::from_raw(raw) } - } - - /// Consumes the `PinBox`, returning the wrapped raw pointer. - /// - /// After calling this function, the caller is responsible for the - /// memory previously managed by the `PinBox`. In particular, the - /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the raw pointer back into a - /// `PinBox` with the [`PinBox::from_raw`] function. - /// - /// Note: this is an associated function, which means that you have - /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This - /// is so that there is no conflict with a method on the inner type. - /// - /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw - /// - /// # Examples - /// - /// ``` - /// #![feature(pin)] - /// use std::pin::PinBox; - /// let x = PinBox::new(5); - /// let ptr = PinBox::into_raw(x); - /// ``` - #[inline] - pub fn into_raw(b: PinBox<T>) -> *mut T { - Box::into_raw(b.inner) - } - - /// Get a mutable reference to the data inside this PinBox. - /// - /// This function is unsafe. Users must guarantee that the data is never - /// moved out of this reference. - #[inline] - pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T { - &mut *this.inner - } - - /// Convert this PinBox into an unpinned Box. - /// - /// This function is unsafe. Users must guarantee that the data is never - /// moved out of the box. - #[inline] - pub unsafe fn unpin(this: PinBox<T>) -> Box<T> { - this.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<T: ?Sized> From<Box<T>> for PinBox<T> { - fn from(boxed: Box<T>) -> PinBox<T> { - PinBox { inner: boxed } - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<T: ?Sized> Deref for PinBox<T> { - type Target = T; - - fn deref(&self) -> &T { - &*self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<T: Unpin + ?Sized> DerefMut for PinBox<T> { - fn deref_mut(&mut self) -> &mut T { - &mut *self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<T: fmt::Display + ?Sized> fmt::Display for PinBox<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&*self.inner, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<T: fmt::Debug + ?Sized> fmt::Debug for PinBox<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&*self.inner, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<T: ?Sized> fmt::Pointer for PinBox<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // It's not possible to extract the inner Uniq directly from the Box, - // instead we cast it to a *const which aliases the Unique - let ptr: *const T = &*self.inner; - fmt::Pointer::fmt(&ptr, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {} - -#[unstable(feature = "pin", issue = "49150")] -impl<T: ?Sized> Unpin for PinBox<T> {} - -#[unstable(feature = "futures_api", issue = "50547")] -impl<F: ?Sized + Future> Future for PinBox<F> { - type Output = F::Output; - - fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> { - self.as_pin_mut().poll(cx) - } -} - -#[unstable(feature = "futures_api", issue = "50547")] -unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox<F> - where F: Future<Output = T> + 'a -{ - fn into_raw(self) -> *mut () { - PinBox::into_raw(self) as *mut () - } - - unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> { - let ptr = ptr as *mut F; - let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr); - pin.poll(cx) - } - - unsafe fn drop(ptr: *mut ()) { - drop(PinBox::from_raw(ptr as *mut F)) - } -} - -#[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: Future<Output = ()> + Send + 'a> From<PinBox<F>> for FutureObj<'a, ()> { - fn from(boxed: PinBox<F>) -> Self { - FutureObj::new(boxed) - } -} - -#[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: Future<Output = ()> + 'a> From<PinBox<F>> for LocalFutureObj<'a, ()> { - fn from(boxed: PinBox<F>) -> Self { - LocalFutureObj::new(boxed) - } -} diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 4860daa11e2..3b8b65dc314 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -256,6 +256,7 @@ use core::marker::{Unsize, PhantomData}; use core::mem::{self, align_of_val, forget, size_of_val}; use core::ops::Deref; use core::ops::CoerceUnsized; +use core::pin::Pin; use core::ptr::{self, NonNull}; use core::convert::From; use core::usize; @@ -321,6 +322,11 @@ impl<T> Rc<T> { } } + #[unstable(feature = "pin", issue = "49150")] + pub fn pinned(value: T) -> Pin<Rc<T>> { + unsafe { Pin::new_unchecked(Rc::new(value)) } + } + /// Returns the contained value, if the `Rc` has exactly one strong reference. /// /// Otherwise, an [`Err`][result] is returned with the same `Rc` that was diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 2cd7898f4c7..d9607af1902 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -26,6 +26,7 @@ use core::intrinsics::abort; use core::mem::{self, align_of_val, size_of_val}; use core::ops::Deref; use core::ops::CoerceUnsized; +use core::pin::Pin; use core::ptr::{self, NonNull}; use core::marker::{Unsize, PhantomData}; use core::hash::{Hash, Hasher}; @@ -296,6 +297,11 @@ impl<T> Arc<T> { Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData } } + #[unstable(feature = "pin", issue = "49150")] + pub fn pinned(data: T) -> Pin<Arc<T>> { + unsafe { Pin::new_unchecked(Arc::new(data)) } + } + /// Returns the contained value, if the `Arc` has exactly one strong reference. /// /// Otherwise, an [`Err`][result] is returned with the same `Arc` that was |
