From 974bdc80fe3214159dc30e0bbb76694900e613c0 Mon Sep 17 00:00:00 2001 From: Without Boats Date: Sat, 1 Sep 2018 06:12:10 +0200 Subject: [PATCH 1/4] Update to a new pinning API. --- src/liballoc/boxed.rs | 38 +++- src/liballoc/lib.rs | 1 - src/liballoc/pin.rs | 302 ---------------------------- src/liballoc/rc.rs | 6 + src/liballoc/sync.rs | 6 + src/libcore/future/future.rs | 19 +- src/libcore/future/future_obj.rs | 35 +++- src/libcore/marker.rs | 8 +- src/libcore/option.rs | 20 +- src/libcore/pin.rs | 334 +++++++++++++++++++++---------- src/libstd/future.rs | 10 +- src/libstd/lib.rs | 2 +- src/libstd/macros.rs | 2 +- src/libstd/panic.rs | 8 +- 14 files changed, 340 insertions(+), 451 deletions(-) delete mode 100644 src/liballoc/pin.rs 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::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 Box { pub fn new(x: T) -> Box { box x } + + #[unstable(feature = "pin", issue = "49150")] + pub fn pinned(x: T) -> Pin> { + unsafe { Pin::new_unchecked(box x) } + } } impl Box { @@ -427,6 +431,13 @@ fn from(t: T) -> Self { } } +#[unstable(feature = "pin", issue = "49150")] +impl From> for Pin> { + fn from(boxed: Box) -> 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 @@ unsafe fn resume(&mut self) -> GeneratorState { impl Future for Box { type Output = F::Output; - fn poll(mut self: PinMut, cx: &mut Context) -> Poll { - PinMut::new(&mut **self).poll(cx) + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { + F::poll(Pin::new(&mut *self), cx) } } @@ -779,8 +790,8 @@ fn into_raw(self) -> *mut () { unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { let ptr = ptr as *mut F; - let pin: PinMut = 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 @@ fn from(boxed: Box) -> Self { } } -#[unstable(feature = "pin", issue = "49150")] -impl From> for Box { - fn from(pinned: PinBox) -> Box { - unsafe { PinBox::unpin(pinned) } +#[unstable(feature = "futures_api", issue = "50547")] +impl<'a, F: Future + Send + 'a> From>> for FutureObj<'a, ()> { + fn from(boxed: Pin>) -> Self { + FutureObj::new(boxed) + } +} + +#[unstable(feature = "futures_api", issue = "50547")] +impl<'a, F: Future + 'a> From>> for LocalFutureObj<'a, ()> { + fn from(boxed: Pin>) -> 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 @@ mod boxed { 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, -//! _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 { -//! 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 { - inner: Box, -} - -#[unstable(feature = "pin", issue = "49150")] -impl PinBox { - /// Allocate memory on the heap, move the data into it and pin it. - #[unstable(feature = "pin", issue = "49150")] - pub fn new(data: T) -> PinBox { - PinBox { inner: Box::new(data) } - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl PinBox { - /// 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) -> *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) -> &'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) -> Box { - this.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl From> for PinBox { - fn from(boxed: Box) -> PinBox { - PinBox { inner: boxed } - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl Deref for PinBox { - type Target = T; - - fn deref(&self) -> &T { - &*self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl DerefMut for PinBox { - fn deref_mut(&mut self) -> &mut T { - &mut *self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Display for PinBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&*self.inner, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Debug for PinBox { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&*self.inner, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl fmt::Pointer for PinBox { - 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, U: ?Sized> CoerceUnsized> for PinBox {} - -#[unstable(feature = "pin", issue = "49150")] -impl Unpin for PinBox {} - -#[unstable(feature = "futures_api", issue = "50547")] -impl Future for PinBox { - type Output = F::Output; - - fn poll(mut self: PinMut, cx: &mut Context) -> Poll { - self.as_pin_mut().poll(cx) - } -} - -#[unstable(feature = "futures_api", issue = "50547")] -unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox - where F: Future + 'a -{ - fn into_raw(self) -> *mut () { - PinBox::into_raw(self) as *mut () - } - - unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { - let ptr = ptr as *mut F; - let pin: PinMut = 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 + Send + 'a> From> for FutureObj<'a, ()> { - fn from(boxed: PinBox) -> Self { - FutureObj::new(boxed) - } -} - -#[unstable(feature = "futures_api", issue = "50547")] -impl<'a, F: Future + 'a> From> for LocalFutureObj<'a, ()> { - fn from(boxed: PinBox) -> 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::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 @@ pub fn new(value: T) -> Rc { } } + #[unstable(feature = "pin", issue = "49150")] + pub fn pinned(value: T) -> Pin> { + 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::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 @@ pub fn new(data: T) -> Arc { Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData } } + #[unstable(feature = "pin", issue = "49150")] + pub fn pinned(data: T) -> Pin> { + 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 diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 520b6ebbbaa..6cf1925000e 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -12,8 +12,9 @@ reason = "futures in libcore are unstable", issue = "50547")] -use pin::PinMut; use marker::Unpin; +use ops; +use pin::Pin; use task::{self, Poll}; /// A future represents an asychronous computation. @@ -92,21 +93,25 @@ pub trait Future { /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready /// [`cx.waker()`]: ../task/struct.Context.html#method.waker - fn poll(self: PinMut, cx: &mut task::Context) -> Poll; + fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll; } impl<'a, F: ?Sized + Future + Unpin> Future for &'a mut F { type Output = F::Output; - fn poll(mut self: PinMut, cx: &mut task::Context) -> Poll { - F::poll(PinMut::new(&mut **self), cx) + fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { + F::poll(Pin::new(&mut **self), cx) } } -impl<'a, F: ?Sized + Future> Future for PinMut<'a, F> { +impl Future for Pin

where + P: ops::DerefMut + Unpin, + F: Future + ?Sized, +{ type Output = F::Output; - fn poll(mut self: PinMut, cx: &mut task::Context) -> Poll { - F::poll((*self).reborrow(), cx) + fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { + let pin: Pin<&mut F> = Pin::as_mut(&mut *self); + F::poll(pin, cx) } } diff --git a/src/libcore/future/future_obj.rs b/src/libcore/future/future_obj.rs index 68fe461aeae..b335cac6c1d 100644 --- a/src/libcore/future/future_obj.rs +++ b/src/libcore/future/future_obj.rs @@ -15,7 +15,8 @@ use fmt; use future::Future; use marker::{PhantomData, Unpin}; -use pin::PinMut; +use ops; +use pin::Pin; use task::{Context, Poll}; /// A custom trait object for polling futures, roughly akin to @@ -78,9 +79,9 @@ impl<'a, T> Future for LocalFutureObj<'a, T> { type Output = T; #[inline] - fn poll(self: PinMut, cx: &mut Context) -> Poll { + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { unsafe { - (self.poll_fn)(self.ptr, cx) + ((*self).poll_fn)((*self).ptr, cx) } } } @@ -128,9 +129,11 @@ impl<'a, T> Future for FutureObj<'a, T> { type Output = T; #[inline] - fn poll(self: PinMut, cx: &mut Context) -> Poll { - let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) }; - pinned_field.poll(cx) + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { + let pinned_field: Pin<&mut LocalFutureObj<'a, T>> = unsafe { + Pin::map_unchecked_mut(self, |x| &mut x.0) + }; + LocalFutureObj::poll(pinned_field, cx) } } @@ -175,7 +178,25 @@ fn into_raw(self) -> *mut () { } unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { - PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx) + let p: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F)); + F::poll(p, cx) + } + + unsafe fn drop(_ptr: *mut ()) {} +} + +#[unstable(feature = "futures_api", issue = "50547")] +unsafe impl<'a, T, P, F> UnsafeFutureObj<'a, T> for Pin

where + P: ops::DerefMut + 'a, + F: Future + 'a, +{ + fn into_raw(mut self) -> *mut () { + unsafe { Pin::get_mut_unchecked(Pin::as_mut(&mut self)) as *mut F as *mut () } + } + + unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { + let future: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F)); + F::poll(future, cx) } unsafe fn drop(_ptr: *mut ()) {} diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index dd57d2dd009..5572fe1512c 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -609,7 +609,7 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// this trait cannot prevent types from moving by itself. /// /// Instead it can be used to prevent moves through the type system, -/// by controlling the behavior of special pointer types like [`PinMut`], +/// by controlling the behavior of pointers wrapped in the [`Pin`] wrapper, /// which "pin" the type in place by not allowing it to be moved out of them. /// See the [`pin module`] documentation for more information on pinning. /// @@ -621,10 +621,10 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// ```rust /// #![feature(pin)] /// use std::mem::replace; -/// use std::pin::PinMut; +/// use std::pin::Pin; /// /// let mut string = "this".to_string(); -/// let mut pinned_string = PinMut::new(&mut string); +/// let mut pinned_string = Pin::new(&mut string); /// /// // dereferencing the pointer mutably is only possible because String implements Unpin /// replace(&mut *pinned_string, "other".to_string()); @@ -633,7 +633,7 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// This trait is automatically implemented for almost every type. /// /// [`replace`]: ../../std/mem/fn.replace.html -/// [`PinMut`]: ../pin/struct.PinMut.html +/// [`Pin`]: ../pin/struct.Pin.html /// [`pin module`]: ../../std/pin/index.html #[unstable(feature = "pin", issue = "49150")] pub auto trait Unpin {} diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 3879abb0af9..83b1999f18b 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -147,7 +147,7 @@ use iter::{FromIterator, FusedIterator, TrustedLen}; use {hint, mem, ops::{self, Deref}}; -use pin::PinMut; +use pin::Pin; // Note that this is not a lang item per se, but it has a hidden dependency on // `Iterator`, which is one. The compiler assumes that the `next` method of @@ -270,12 +270,24 @@ pub fn as_mut(&mut self) -> Option<&mut T> { } } - /// Converts from `Option` to `Option>` + + /// Converts from `Pin<&Option>` to `Option>` #[inline] #[unstable(feature = "pin", issue = "49150")] - pub fn as_pin_mut<'a>(self: PinMut<'a, Self>) -> Option> { + pub fn as_pin_ref<'a>(self: Pin<&'a Option>) -> Option> { unsafe { - PinMut::get_mut_unchecked(self).as_mut().map(|x| PinMut::new_unchecked(x)) + let option: Option<&'a T> = Pin::get(self).as_ref(); + option.map(|x| Pin::new_unchecked(x)) + } + } + + /// Converts from `Pin<&mut Option>` to `Option>` + #[inline] + #[unstable(feature = "pin", issue = "49150")] + pub fn as_pin_mut<'a>(self: Pin<&'a mut Option>) -> Option> { + unsafe { + let option: Option<&'a mut T> = Pin::get_mut_unchecked(self).as_mut(); + option.map(|x| Pin::new_unchecked(x)) } } diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index e9001f86b35..29fc52fe3a0 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -1,21 +1,103 @@ //! Types which pin data to its location in memory //! -//! See the [standard library module] for more information. +//! 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. //! -//! [standard library module]: ../../std/pin/index.html +//! 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 a pointer to the data in the [`Pin`] type. A pointer wrapped +//! in a `Pin` is otherwise equivalent to its normal version, e.g. `Pin>` +//! and `Box` work the same way except that the first is pinning the value +//! of `T` in place. +//! +//! 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. +//! +//! [`Pin`]: struct.Pin.html +//! [`Unpin`]: trait.Unpin.html +//! [`swap`]: ../../std/mem/fn.swap.html +//! [`Box`]: ../boxed/struct.Box.html +//! +//! # Examples +//! +//! ```rust +//! #![feature(pin)] +//! +//! use std::pin::Pin; +//! 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, +//! _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) -> Pin> { +//! 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 = Box::pinned(res); +//! +//! let slice = NonNull::from(&boxed.data); +//! // we know this is safe because modifying a field doesn't move the whole struct +//! unsafe { +//! let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed); +//! Pin::get_mut_unchecked(mut_ref).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")] use fmt; -use future::{Future, UnsafeFutureObj}; use marker::{Sized, Unpin, Unsize}; -use task::{Context, Poll}; use ops::{Deref, DerefMut, CoerceUnsized}; -/// A pinned reference. +/// A pinned pointer. /// -/// This type is similar to a mutable reference, except that it pins its value, -/// which prevents it from moving out of the reference, unless it implements [`Unpin`]. +/// This is a wrapper around a kind of pointer which makes that pointer "pin" its +/// value in place, preventing the value referenced by that pointer from being moved +/// unless it implements [`Unpin`]. /// /// See the [`pin` module] documentation for furthur explanation on pinning. /// @@ -23,138 +105,180 @@ /// [`pin` module]: ../../std/pin/index.html #[unstable(feature = "pin", issue = "49150")] #[fundamental] -pub struct PinMut<'a, T: ?Sized + 'a> { - inner: &'a mut T, +#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] +pub struct Pin

{ + pointer: P, } -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unpin> PinMut<'a, T> { - /// Construct a new `PinMut` around a reference to some data of a type that +impl Pin

where + P: Deref, + T: ?Sized + Unpin, +{ + /// Construct a new `Pin` around a pointer to some data of a type that /// implements `Unpin`. #[unstable(feature = "pin", issue = "49150")] - pub fn new(reference: &'a mut T) -> PinMut<'a, T> { - PinMut { inner: reference } - } - - /// Get a mutable reference to the data inside of this `PinMut`. - #[unstable(feature = "pin", issue = "49150")] - pub fn get_mut(this: PinMut<'a, T>) -> &'a mut T { - this.inner + pub fn new(pointer: P) -> Pin

{ + unsafe { Pin::new_unchecked(pointer) } } } - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> PinMut<'a, T> { - /// Construct a new `PinMut` around a reference to some data of a type that +impl Pin

where + P: Deref, + T: ?Sized, +{ + /// Construct a new `Pin` around a reference to some data of a type that /// may or may not implement `Unpin`. /// - /// This constructor is unsafe because we do not know what will happen with - /// that data after the lifetime of the reference ends. If you cannot guarantee that the - /// data will never move again, calling this constructor is invalid. - #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn new_unchecked(reference: &'a mut T) -> PinMut<'a, T> { - PinMut { inner: reference } - } - - /// Reborrow a `PinMut` for a shorter lifetime. + /// # Safety /// - /// For example, `PinMut::get_mut(x.reborrow())` (unsafely) returns a - /// short-lived mutable reference reborrowing from `x`. + /// This constructor is unsafe because we cannot guarantee that the target data + /// is properly pinned by this pointer. If the constructed `Pin

` does not guarantee + /// that the data is "pinned," constructing a `Pin

` is undefined behavior and could lead + /// to segmentation faults or worse. #[unstable(feature = "pin", issue = "49150")] - pub fn reborrow<'b>(&'b mut self) -> PinMut<'b, T> { - PinMut { inner: self.inner } + pub unsafe fn new_unchecked(pointer: P) -> Pin

{ + Pin { pointer } } - /// Get a mutable reference to the data inside of this `PinMut`. - /// - /// This function is unsafe. You must guarantee that you will never move - /// the data out of the mutable reference you receive when you call this - /// function. + + /// Get a pinned shared reference from this pinned pointer. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn get_mut_unchecked(this: PinMut<'a, T>) -> &'a mut T { - this.inner + pub fn as_ref(this: &Pin

) -> Pin<&T> { + unsafe { Pin::new_unchecked(&**this) } + } +} + +impl Pin

where + P: DerefMut, + T: ?Sized, +{ + /// Get a pinned mutable reference from this pinned pointer. + #[unstable(feature = "pin", issue = "49150")] + pub fn as_mut(this: &mut Pin

) -> Pin<&mut T> { + unsafe { Pin::new_unchecked(&mut *this.pointer) } } + /// Assign a new value to the memory behind the pinned reference. + #[unstable(feature = "pin", issue = "49150")] + pub fn set(this: Pin<&mut T>, value: T) + where T: Sized, + { + *this.pointer = value; + } +} + +impl<'a, T> Pin<&'a T> { /// Construct a new pin by mapping the interior value. /// - /// For example, if you wanted to get a `PinMut` of a field of something, + /// For example, if you wanted to get a `Pin` of a field of something, /// you could use this to get access to that field in one line of code. /// + /// # Safety + /// /// This function is unsafe. You must guarantee that the data you return /// will not move so long as the argument value does not move (for example, /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn map_unchecked(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where - F: FnOnce(&mut T) -> &mut U + pub unsafe fn map_unchecked(this: Pin<&'a T>, func: F) -> Pin<&'a U> where + F: FnOnce(&T) -> &U, { - PinMut { inner: f(this.inner) } + let pointer = &*this.pointer; + let new_pointer = func(pointer); + Pin::new_unchecked(new_pointer) } - /// Assign a new value to the memory behind the pinned reference. + /// Get a safe reference out of a pin. #[unstable(feature = "pin", issue = "49150")] - pub fn set(this: PinMut<'a, T>, value: T) - where T: Sized, + pub fn get(this: Pin<&'a T>) -> &'a T { + this.pointer + } +} + +impl<'a, T> Pin<&'a mut T> { + /// Get a mutable reference to the data inside of this `Pin`. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that you will never move + /// the data out of the mutable reference you receive when you call this + /// function, so that the invariants on the `Pin` type can be upheld. + #[unstable(feature = "pin", issue = "49150")] + pub unsafe fn get_mut_unchecked(this: Pin<&'a mut T>) -> &'a mut T { + this.pointer + } + + /// Construct a new pin by mapping the interior value. + /// + /// For example, if you wanted to get a `Pin` of a field of something, + /// you could use this to get access to that field in one line of code. + /// + /// # Safety + /// + /// This function is unsafe. You must guarantee that the data you return + /// will not move so long as the argument value does not move (for example, + /// because it is one of the fields of that value), and also that you do + /// not move out of the argument you receive to the interior function. + #[unstable(feature = "pin", issue = "49150")] + pub unsafe fn map_unchecked_mut(this: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where + F: FnOnce(&mut T) -> &mut U, { - *this.inner = value; + let pointer = Pin::get_mut_unchecked(this); + let new_pointer = func(pointer); + Pin::new_unchecked(new_pointer) } } #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> Deref for PinMut<'a, T> { - type Target = T; - - fn deref(&self) -> &T { - &*self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unpin> DerefMut for PinMut<'a, T> { - fn deref_mut(&mut self) -> &mut T { - self.inner - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for PinMut<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinMut<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&**self, f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> fmt::Pointer for PinMut<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Pointer::fmt(&(&*self.inner as *const T), f) - } -} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for PinMut<'a, T> {} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {} - -#[unstable(feature = "futures_api", issue = "50547")] -unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinMut<'a, F> - where F: Future + 'a +impl Deref for Pin

where + P: Deref, + T: ?Sized, { - fn into_raw(self) -> *mut () { - unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () } + type Target = T; + fn deref(&self) -> &T { + &*self.pointer } - - unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll { - PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx) - } - - unsafe fn drop(_ptr: *mut ()) {} } + +#[unstable(feature = "pin", issue = "49150")] +impl DerefMut for Pin

where + P: DerefMut, + T: ?Sized + Unpin, +{ + fn deref_mut(&mut self) -> &mut T { + &mut *self.pointer + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, P: fmt::Debug> fmt::Debug for Pin

{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.pointer, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, P: fmt::Display> fmt::Display for Pin

{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.pointer, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, P: fmt::Pointer> fmt::Pointer for Pin

{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Pointer::fmt(&self.pointer, f) + } +} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Pin<&'a T> {} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Pin<&'a mut T> {} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized> Unpin for Pin<&'a T> {} + +#[unstable(feature = "pin", issue = "49150")] +impl<'a, T: ?Sized> Unpin for Pin<&'a mut T> {} diff --git a/src/libstd/future.rs b/src/libstd/future.rs index d9657f691c7..262646738cf 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -12,7 +12,7 @@ use core::cell::Cell; use core::marker::Unpin; -use core::pin::PinMut; +use core::pin::Pin; use core::option::Option; use core::ptr::NonNull; use core::task::{self, Poll}; @@ -42,8 +42,8 @@ impl> !Unpin for GenFuture {} #[unstable(feature = "gen_future", issue = "50547")] impl> Future for GenFuture { type Output = T::Return; - fn poll(self: PinMut, cx: &mut task::Context) -> Poll { - set_task_cx(cx, || match unsafe { PinMut::get_mut_unchecked(self).0.resume() } { + fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { + set_task_cx(cx, || match unsafe { Pin::get_mut_unchecked(self).0.resume() } { GeneratorState::Yielded(()) => Poll::Pending, GeneratorState::Complete(x) => Poll::Ready(x), }) @@ -108,9 +108,9 @@ pub fn get_task_cx(f: F) -> R #[unstable(feature = "gen_future", issue = "50547")] /// Polls a future in the current thread-local task context. -pub fn poll_in_task_cx(f: PinMut) -> Poll +pub fn poll_in_task_cx(f: Pin<&mut F>) -> Poll where F: Future { - get_task_cx(|cx| f.poll(cx)) + get_task_cx(|cx| F::poll(f, cx)) } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 310475d31fd..fac8c35b9c9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -436,7 +436,7 @@ #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::format; #[unstable(feature = "pin", issue = "49150")] -pub use alloc_crate::pin; +pub use core::pin; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::slice; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 6945a41a5e7..b9a709d80be 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -230,7 +230,7 @@ macro_rules! await { loop { if let $crate::task::Poll::Ready(x) = $crate::future::poll_in_task_cx(unsafe { - $crate::pin::PinMut::new_unchecked(&mut pinned) + $crate::pin::Pin::new_unchecked(&mut pinned) }) { break x; diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 47547aedcbd..bd7a92e9b3f 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -16,7 +16,7 @@ use cell::UnsafeCell; use fmt; use future::Future; -use pin::PinMut; +use pin::Pin; use ops::{Deref, DerefMut}; use panicking; use ptr::{Unique, NonNull}; @@ -327,9 +327,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { impl<'a, F: Future> Future for AssertUnwindSafe { type Output = F::Output; - fn poll(self: PinMut, cx: &mut task::Context) -> Poll { - let pinned_field = unsafe { PinMut::map_unchecked(self, |x| &mut x.0) }; - pinned_field.poll(cx) + fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { + let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) }; + F::poll(pinned_field, cx) } } From 3ec1810e329bb9dfa0cf0686bdc13558771785d2 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Fri, 14 Sep 2018 17:40:52 -0700 Subject: [PATCH 2/4] Cleanup and fix method resolution issue --- src/liballoc/boxed.rs | 6 +- src/libcore/future/future.rs | 14 +-- src/libcore/option.rs | 6 +- src/libcore/pin.rs | 142 ++++++++++++++++++++----------- src/test/run-pass/async-await.rs | 11 ++- src/test/run-pass/futures-api.rs | 11 ++- 6 files changed, 117 insertions(+), 73 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index fce6417186f..744b611c061 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -98,8 +98,9 @@ pub fn new(x: T) -> Box { } #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] pub fn pinned(x: T) -> Pin> { - unsafe { Pin::new_unchecked(box x) } + (box x).into() } } @@ -434,6 +435,9 @@ fn from(t: T) -> Self { #[unstable(feature = "pin", issue = "49150")] impl From> for Pin> { fn from(boxed: Box) -> Self { + // It's not possible to move or replace the insides of a `Pin>` + // when `T: !Unpin`, so it's safe to pin it directly without any + // additional requirements. unsafe { Pin::new_unchecked(boxed) } } } diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 6cf1925000e..f4b5cf95e37 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -104,14 +104,14 @@ fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll } } -impl Future for Pin

where - P: ops::DerefMut + Unpin, - F: Future + ?Sized, +impl

Future for Pin

+where + P: ops::DerefMut, + P::Target: Future, { - type Output = F::Output; + type Output = <

::Target as Future>::Output; - fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { - let pin: Pin<&mut F> = Pin::as_mut(&mut *self); - F::poll(pin, cx) + fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { + Pin::get_mut(self).as_mut().poll(cx) } } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 83b1999f18b..5d81d21d1df 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -276,8 +276,7 @@ pub fn as_mut(&mut self) -> Option<&mut T> { #[unstable(feature = "pin", issue = "49150")] pub fn as_pin_ref<'a>(self: Pin<&'a Option>) -> Option> { unsafe { - let option: Option<&'a T> = Pin::get(self).as_ref(); - option.map(|x| Pin::new_unchecked(x)) + Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) } } @@ -286,8 +285,7 @@ pub fn as_pin_ref<'a>(self: Pin<&'a Option>) -> Option> { #[unstable(feature = "pin", issue = "49150")] pub fn as_pin_mut<'a>(self: Pin<&'a mut Option>) -> Option> { unsafe { - let option: Option<&'a mut T> = Pin::get_mut_unchecked(self).as_mut(); - option.map(|x| Pin::new_unchecked(x)) + Pin::get_mut_unchecked(self).as_mut().map(|x| Pin::new_unchecked(x)) } } diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 29fc52fe3a0..3ab6dcd8531 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -7,7 +7,7 @@ //! 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*, +//! In order to prevent objects from moving, they must be pinned //! by wrapping a pointer to the data in the [`Pin`] type. A pointer wrapped //! in a `Pin` is otherwise equivalent to its normal version, e.g. `Pin>` //! and `Box` work the same way except that the first is pinning the value @@ -15,7 +15,7 @@ //! //! 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`], +//! 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. //! @@ -28,7 +28,7 @@ //! [`Pin`]: struct.Pin.html //! [`Unpin`]: trait.Unpin.html //! [`swap`]: ../../std/mem/fn.swap.html -//! [`Box`]: ../boxed/struct.Box.html +//! [`Box`]: ../../std/boxed/struct.Box.html //! //! # Examples //! @@ -66,7 +66,7 @@ //! //! let slice = NonNull::from(&boxed.data); //! // we know this is safe because modifying a field doesn't move the whole struct -//! unsafe { +//! unsafe { //! let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed); //! Pin::get_mut_unchecked(mut_ref).slice = slice; //! } @@ -90,9 +90,12 @@ #![unstable(feature = "pin", issue = "49150")] use fmt; -use marker::{Sized, Unpin, Unsize}; +use marker::Sized; use ops::{Deref, DerefMut, CoerceUnsized}; +#[doc(inline)] +pub use marker::Unpin; + /// A pinned pointer. /// /// This is a wrapper around a kind of pointer which makes that pointer "pin" its @@ -103,6 +106,9 @@ /// /// [`Unpin`]: ../../std/marker/trait.Unpin.html /// [`pin` module]: ../../std/pin/index.html +// +// Note: the derives below are allowed because they all only use `&P`, so they +// cannot move the value behind `pointer`. #[unstable(feature = "pin", issue = "49150")] #[fundamental] #[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] @@ -110,64 +116,68 @@ pub struct Pin

{ pointer: P, } -impl Pin

where - P: Deref, - T: ?Sized + Unpin, +impl Pin

+where + P::Target: Unpin, { /// Construct a new `Pin` around a pointer to some data of a type that /// implements `Unpin`. #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] pub fn new(pointer: P) -> Pin

{ + // Safety: the value pointed to is `Unpin`, and so has no requirements + // around pinning. unsafe { Pin::new_unchecked(pointer) } } } -impl Pin

where - P: Deref, - T: ?Sized, -{ +impl Pin

{ /// Construct a new `Pin` around a reference to some data of a type that /// may or may not implement `Unpin`. /// /// # Safety /// - /// This constructor is unsafe because we cannot guarantee that the target data - /// is properly pinned by this pointer. If the constructed `Pin

` does not guarantee - /// that the data is "pinned," constructing a `Pin

` is undefined behavior and could lead - /// to segmentation faults or worse. + /// This constructor is unsafe because we cannot guarantee that the data + /// pointed to by `pointer` is pinned. If the constructed `Pin

` does + /// not guarantee that the data `P` points to is pinned, constructing a + /// `Pin

` is undefined behavior. + /// + /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used + /// instead. #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] pub unsafe fn new_unchecked(pointer: P) -> Pin

{ Pin { pointer } } - /// Get a pinned shared reference from this pinned pointer. #[unstable(feature = "pin", issue = "49150")] - pub fn as_ref(this: &Pin

) -> Pin<&T> { - unsafe { Pin::new_unchecked(&**this) } + #[inline(always)] + pub fn as_ref(self: &Pin

) -> Pin<&P::Target> { + unsafe { Pin::new_unchecked(&**self) } } } -impl Pin

where - P: DerefMut, - T: ?Sized, -{ +impl Pin

{ /// Get a pinned mutable reference from this pinned pointer. #[unstable(feature = "pin", issue = "49150")] - pub fn as_mut(this: &mut Pin

) -> Pin<&mut T> { - unsafe { Pin::new_unchecked(&mut *this.pointer) } + #[inline(always)] + pub fn as_mut(self: &mut Pin

) -> Pin<&mut P::Target> { + unsafe { Pin::new_unchecked(&mut *self.pointer) } } /// Assign a new value to the memory behind the pinned reference. #[unstable(feature = "pin", issue = "49150")] - pub fn set(this: Pin<&mut T>, value: T) - where T: Sized, + #[inline(always)] + pub fn set(mut self: Pin

, value: P::Target) + where + P::Target: Sized, { - *this.pointer = value; + *self.pointer = value; } } -impl<'a, T> Pin<&'a T> { +impl<'a, T: ?Sized> Pin<&'a T> { /// Construct a new pin by mapping the interior value. /// /// For example, if you wanted to get a `Pin` of a field of something, @@ -188,14 +198,45 @@ pub unsafe fn map_unchecked(this: Pin<&'a T>, func: F) -> Pin<&'a U> where Pin::new_unchecked(new_pointer) } - /// Get a safe reference out of a pin. + /// Get a shared reference out of a pin. + /// + /// Note: `Pin` also implements `Deref` to the target, which can be used + /// to access the inner value. However, `Deref` only provides a reference + /// that lives for as long as the borrow of the `Pin`, not the lifetime of + /// the `Pin` itself. This method allows turning the `Pin` into a reference + /// with the same lifetime as the original `Pin`. #[unstable(feature = "pin", issue = "49150")] - pub fn get(this: Pin<&'a T>) -> &'a T { + #[inline(always)] + pub fn get_ref(this: Pin<&'a T>) -> &'a T { this.pointer } } impl<'a, T> Pin<&'a mut T> { + /// Convert this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. + #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] + pub fn into_ref(this: Pin<&'a mut T>) -> Pin<&'a T> { + Pin { pointer: this.pointer } + } + + /// Get a mutable reference to the data inside of this `Pin`. + /// + /// This requires that the data inside this `Pin` is `Unpin`. + /// + /// Note: `Pin` also implements `DerefMut` to the data, which can be used + /// to access the inner value. However, `DerefMut` only provides a reference + /// that lives for as long as the borrow of the `Pin`, not the lifetime of + /// the `Pin` itself. This method allows turning the `Pin` into a reference + /// with the same lifetime as the original `Pin`. + #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] + pub fn get_mut(this: Pin<&'a mut T>) -> &'a mut T + where T: Unpin, + { + this.pointer + } + /// Get a mutable reference to the data inside of this `Pin`. /// /// # Safety @@ -203,7 +244,11 @@ impl<'a, T> Pin<&'a mut T> { /// This function is unsafe. You must guarantee that you will never move /// the data out of the mutable reference you receive when you call this /// function, so that the invariants on the `Pin` type can be upheld. + /// + /// If the underlying data is `Unpin`, `Pin::get_mut` should be used + /// instead. #[unstable(feature = "pin", issue = "49150")] + #[inline(always)] pub unsafe fn get_mut_unchecked(this: Pin<&'a mut T>) -> &'a mut T { this.pointer } @@ -230,22 +275,19 @@ pub unsafe fn map_unchecked_mut(this: Pin<&'a mut T>, func: F) -> Pin<&'a } #[unstable(feature = "pin", issue = "49150")] -impl Deref for Pin

where - P: Deref, - T: ?Sized, -{ - type Target = T; - fn deref(&self) -> &T { +impl Deref for Pin

{ + type Target = P::Target; + fn deref(&self) -> &P::Target { &*self.pointer } } #[unstable(feature = "pin", issue = "49150")] -impl DerefMut for Pin

where - P: DerefMut, - T: ?Sized + Unpin, +impl DerefMut for Pin

+where + P::Target: Unpin { - fn deref_mut(&mut self) -> &mut T { + fn deref_mut(&mut self) -> &mut P::Target { &mut *self.pointer } } @@ -271,14 +313,16 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } } +// Note: this means that any impl of `CoerceUnsized` that allows coercing from +// a type that impls `Deref` to a type that impls +// `Deref` is unsound. Any such impl would probably be unsound +// for other reasons, though, so we just need to take care not to allow such +// impls to land in std. #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Pin<&'a T> {} +impl<'a, P, U> CoerceUnsized> for Pin

+where + P: CoerceUnsized, +{} #[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for Pin<&'a mut T> {} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> Unpin for Pin<&'a T> {} - -#[unstable(feature = "pin", issue = "49150")] -impl<'a, T: ?Sized> Unpin for Pin<&'a mut T> {} +impl<'a, P> Unpin for Pin

{} diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index 46f22845907..cdd65bfddd3 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -12,8 +12,7 @@ #![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)] -use std::pin::PinBox; -use std::pin::PinMut; +use std::pin::Pin; use std::future::Future; use std::sync::{ Arc, @@ -49,7 +48,7 @@ fn wake_and_yield_once() -> WakeOnceThenComplete { WakeOnceThenComplete(false) } impl Future for WakeOnceThenComplete { type Output = (); - fn poll(mut self: PinMut, cx: &mut Context) -> Poll<()> { + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> { if self.0 { Poll::Ready(()) } else { @@ -124,16 +123,16 @@ fn test_future_yields_once_then_returns(f: F) F: FnOnce(u8) -> Fut, Fut: Future, { - let mut fut = PinBox::new(f(9)); + let mut fut = Box::pinned(f(9)); let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); let waker = local_waker_from_nonlocal(counter.clone()); let spawner = &mut NoopSpawner; let cx = &mut Context::new(&waker, spawner); assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst)); - assert_eq!(Poll::Pending, fut.as_pin_mut().poll(cx)); + assert_eq!(Poll::Pending, fut.as_mut().poll(cx)); assert_eq!(1, counter.wakes.load(atomic::Ordering::SeqCst)); - assert_eq!(Poll::Ready(9), fut.as_pin_mut().poll(cx)); + assert_eq!(Poll::Ready(9), fut.as_mut().poll(cx)); } fn main() { diff --git a/src/test/run-pass/futures-api.rs b/src/test/run-pass/futures-api.rs index 69a04437691..6e757fb4f9a 100644 --- a/src/test/run-pass/futures-api.rs +++ b/src/test/run-pass/futures-api.rs @@ -11,9 +11,8 @@ #![feature(arbitrary_self_types, futures_api, pin)] #![allow(unused)] -use std::pin::PinBox; use std::future::Future; -use std::pin::PinMut; +use std::pin::Pin; use std::rc::Rc; use std::sync::{ Arc, @@ -54,12 +53,12 @@ fn spawn_obj(&mut self, _: FutureObj<'static, ()>) -> Result<(), SpawnObjError> impl Future for MyFuture { type Output = (); - fn poll(self: PinMut, cx: &mut Context) -> Poll { + fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll { // Ensure all the methods work appropriately cx.waker().wake(); cx.waker().wake(); cx.local_waker().wake(); - cx.spawner().spawn_obj(PinBox::new(MyFuture).into()).unwrap(); + cx.spawner().spawn_obj(Box::pinned(MyFuture).into()).unwrap(); Poll::Ready(()) } } @@ -72,7 +71,7 @@ fn test_local_waker() { let waker = unsafe { local_waker(counter.clone()) }; let spawner = &mut NoopSpawner; let cx = &mut Context::new(&waker, spawner); - assert_eq!(Poll::Ready(()), PinMut::new(&mut MyFuture).poll(cx)); + assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(cx)); assert_eq!(1, counter.local_wakes.load(atomic::Ordering::SeqCst)); assert_eq!(2, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst)); } @@ -85,7 +84,7 @@ fn test_local_as_nonlocal_waker() { let waker: LocalWaker = local_waker_from_nonlocal(counter.clone()); let spawner = &mut NoopSpawner; let cx = &mut Context::new(&waker, spawner); - assert_eq!(Poll::Ready(()), PinMut::new(&mut MyFuture).poll(cx)); + assert_eq!(Poll::Ready(()), Pin::new(&mut MyFuture).poll(cx)); assert_eq!(0, counter.local_wakes.load(atomic::Ordering::SeqCst)); assert_eq!(3, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst)); } From 403d12d696a344cd6a9251e46c313e00f0316f9b Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 18 Sep 2018 01:42:27 -0700 Subject: [PATCH 3/4] Remove outdated rustdoc PinBox tests --- src/test/rustdoc-js/pinbox-new.js | 20 -------------------- src/test/rustdoc-js/vec-new.js | 1 - 2 files changed, 21 deletions(-) delete mode 100644 src/test/rustdoc-js/pinbox-new.js diff --git a/src/test/rustdoc-js/pinbox-new.js b/src/test/rustdoc-js/pinbox-new.js deleted file mode 100644 index 55842dc8e45..00000000000 --- a/src/test/rustdoc-js/pinbox-new.js +++ /dev/null @@ -1,20 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// exact-check - -const QUERY = 'pinbox::new'; - -const EXPECTED = { - 'others': [ - { 'path': 'std::pin::PinBox', 'name': 'new' }, - { 'path': 'alloc::pin::PinBox', 'name': 'new' }, - ], -}; diff --git a/src/test/rustdoc-js/vec-new.js b/src/test/rustdoc-js/vec-new.js index 4a654ccb135..42951724648 100644 --- a/src/test/rustdoc-js/vec-new.js +++ b/src/test/rustdoc-js/vec-new.js @@ -14,6 +14,5 @@ const EXPECTED = { 'others': [ { 'path': 'std::vec::Vec', 'name': 'new' }, { 'path': 'std::vec::Vec', 'name': 'ne' }, - { 'path': 'std::pin::PinBox', 'name': 'new' }, ], }; From 574bca7262f0ddab9e1818253012dbff34755b98 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 18 Sep 2018 11:48:03 -0700 Subject: [PATCH 4/4] Cleanup Deref impls and add ?Sized bound to &mut T impls --- src/libcore/pin.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 3ab6dcd8531..d09a545aecf 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -154,7 +154,7 @@ pub unsafe fn new_unchecked(pointer: P) -> Pin

{ #[unstable(feature = "pin", issue = "49150")] #[inline(always)] pub fn as_ref(self: &Pin

) -> Pin<&P::Target> { - unsafe { Pin::new_unchecked(&**self) } + unsafe { Pin::new_unchecked(&*self.pointer) } } } @@ -212,7 +212,7 @@ pub fn get_ref(this: Pin<&'a T>) -> &'a T { } } -impl<'a, T> Pin<&'a mut T> { +impl<'a, T: ?Sized> Pin<&'a mut T> { /// Convert this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. #[unstable(feature = "pin", issue = "49150")] #[inline(always)] @@ -278,7 +278,7 @@ pub unsafe fn map_unchecked_mut(this: Pin<&'a mut T>, func: F) -> Pin<&'a impl Deref for Pin

{ type Target = P::Target; fn deref(&self) -> &P::Target { - &*self.pointer + Pin::get_ref(Pin::as_ref(self)) } } @@ -288,7 +288,7 @@ impl DerefMut for Pin

P::Target: Unpin { fn deref_mut(&mut self) -> &mut P::Target { - &mut *self.pointer + Pin::get_mut(Pin::as_mut(self)) } }