Auto merge of #53877 - withoutboats:compositional-pin, r=aturon
Update to a new pinning API. ~~Blocked on #53843 because of method resolution problems with new pin type.~~ @r? @cramertj cc @RalfJung @pythonesque anyone interested in #49150
This commit is contained in:
commit
1e21c9a297
@ -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,12 @@ impl<T> Box<T> {
|
||||
pub fn new(x: T) -> Box<T> {
|
||||
box x
|
||||
}
|
||||
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
#[inline(always)]
|
||||
pub fn pinned(x: T) -> Pin<Box<T>> {
|
||||
(box x).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Box<T> {
|
||||
@ -427,6 +432,16 @@ fn from(t: T) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
impl<T> From<Box<T>> for Pin<Box<T>> {
|
||||
fn from(boxed: Box<T>) -> Self {
|
||||
// It's not possible to move or replace the insides of a `Pin<Box<T>>`
|
||||
// when `T: !Unpin`, so it's safe to pin it directly without any
|
||||
// additional requirements.
|
||||
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]> {
|
||||
@ -789,8 +804,8 @@ unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -804,8 +819,8 @@ fn into_raw(self) -> *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)
|
||||
let pin: Pin<&mut F> = Pin::new_unchecked(&mut *ptr);
|
||||
F::poll(pin, cx)
|
||||
}
|
||||
|
||||
unsafe fn drop(ptr: *mut ()) {
|
||||
@ -843,9 +858,16 @@ fn from(boxed: Box<F>) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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<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
|
||||
|
@ -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::{Unpin, Unsize, PhantomData};
|
||||
use core::hash::{Hash, Hasher};
|
||||
@ -297,6 +298,11 @@ pub fn new(data: 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
|
||||
|
@ -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<Self>, cx: &mut task::Context) -> Poll<Self::Output>;
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output>;
|
||||
}
|
||||
|
||||
impl<'a, F: ?Sized + Future + Unpin> Future for &'a mut F {
|
||||
type Output = F::Output;
|
||||
|
||||
fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
|
||||
F::poll(PinMut::new(&mut **self), cx)
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {
|
||||
F::poll(Pin::new(&mut **self), cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, F: ?Sized + Future> Future for PinMut<'a, F> {
|
||||
type Output = F::Output;
|
||||
impl<P> Future for Pin<P>
|
||||
where
|
||||
P: ops::DerefMut,
|
||||
P::Target: Future,
|
||||
{
|
||||
type Output = <<P as ops::Deref>::Target as Future>::Output;
|
||||
|
||||
fn poll(mut self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
|
||||
F::poll((*self).reborrow(), cx)
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {
|
||||
Pin::get_mut(self).as_mut().poll(cx)
|
||||
}
|
||||
}
|
||||
|
@ -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<Self>, cx: &mut Context) -> Poll<T> {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<T> {
|
||||
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<Self>, cx: &mut Context) -> Poll<T> {
|
||||
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<T> {
|
||||
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<T> {
|
||||
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<P> where
|
||||
P: ops::DerefMut<Target = F> + 'a,
|
||||
F: Future<Output = T> + '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<T> {
|
||||
let future: Pin<&mut F> = Pin::new_unchecked(&mut *(ptr as *mut F));
|
||||
F::poll(future, cx)
|
||||
}
|
||||
|
||||
unsafe fn drop(_ptr: *mut ()) {}
|
||||
|
@ -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 {}
|
||||
|
@ -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,22 @@ pub fn as_mut(&mut self) -> Option<&mut T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts from `Option<T>` to `Option<PinMut<'_, T>>`
|
||||
|
||||
/// Converts from `Pin<&Option<T>>` to `Option<Pin<&T>>`
|
||||
#[inline]
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
pub fn as_pin_mut<'a>(self: PinMut<'a, Self>) -> Option<PinMut<'a, T>> {
|
||||
pub fn as_pin_ref<'a>(self: Pin<&'a Option<T>>) -> Option<Pin<&'a T>> {
|
||||
unsafe {
|
||||
PinMut::get_mut_unchecked(self).as_mut().map(|x| PinMut::new_unchecked(x))
|
||||
Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x))
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts from `Pin<&mut Option<T>>` to `Option<Pin<&mut T>>`
|
||||
#[inline]
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
pub fn as_pin_mut<'a>(self: Pin<&'a mut Option<T>>) -> Option<Pin<&'a mut T>> {
|
||||
unsafe {
|
||||
Pin::get_mut_unchecked(self).as_mut().map(|x| Pin::new_unchecked(x))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,160 +1,328 @@
|
||||
//! 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<Box<T>>`
|
||||
//! and `Box<T>` 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`]: ../../std/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<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) -> Pin<Box<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 = 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 marker::Sized;
|
||||
use ops::{Deref, DerefMut, CoerceUnsized};
|
||||
|
||||
/// A pinned reference.
|
||||
#[doc(inline)]
|
||||
pub use marker::Unpin;
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// [`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]
|
||||
pub struct PinMut<'a, T: ?Sized + 'a> {
|
||||
inner: &'a mut T,
|
||||
#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct Pin<P> {
|
||||
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<P: Deref> Pin<P>
|
||||
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")]
|
||||
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
|
||||
#[inline(always)]
|
||||
pub fn new(pointer: P) -> Pin<P> {
|
||||
// Safety: the value pointed to is `Unpin`, and so has no requirements
|
||||
// around pinning.
|
||||
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<P: Deref> Pin<P> {
|
||||
/// 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`.
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
pub fn reborrow<'b>(&'b mut self) -> PinMut<'b, T> {
|
||||
PinMut { inner: self.inner }
|
||||
}
|
||||
|
||||
/// Get a mutable reference to the data inside of this `PinMut`.
|
||||
/// This constructor is unsafe because we cannot guarantee that the data
|
||||
/// pointed to by `pointer` is pinned. If the constructed `Pin<P>` does
|
||||
/// not guarantee that the data `P` points to is pinned, constructing a
|
||||
/// `Pin<P>` is undefined behavior.
|
||||
///
|
||||
/// 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.
|
||||
/// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used
|
||||
/// instead.
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
pub unsafe fn get_mut_unchecked(this: PinMut<'a, T>) -> &'a mut T {
|
||||
this.inner
|
||||
#[inline(always)]
|
||||
pub unsafe fn new_unchecked(pointer: P) -> Pin<P> {
|
||||
Pin { pointer }
|
||||
}
|
||||
|
||||
/// Get a pinned shared reference from this pinned pointer.
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
#[inline(always)]
|
||||
pub fn as_ref(self: &Pin<P>) -> Pin<&P::Target> {
|
||||
unsafe { Pin::new_unchecked(&*self.pointer) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: DerefMut> Pin<P> {
|
||||
/// Get a pinned mutable reference from this pinned pointer.
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
#[inline(always)]
|
||||
pub fn as_mut(self: &mut Pin<P>) -> 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")]
|
||||
#[inline(always)]
|
||||
pub fn set(mut self: Pin<P>, value: P::Target)
|
||||
where
|
||||
P::Target: Sized,
|
||||
{
|
||||
*self.pointer = value;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> 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<U, F>(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where
|
||||
F: FnOnce(&mut T) -> &mut U
|
||||
pub unsafe fn map_unchecked<U, F>(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 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 set(this: PinMut<'a, T>, value: T)
|
||||
where T: Sized,
|
||||
#[inline(always)]
|
||||
pub fn get_ref(this: Pin<&'a T>) -> &'a T {
|
||||
this.pointer
|
||||
}
|
||||
}
|
||||
|
||||
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)]
|
||||
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.inner = value;
|
||||
this.pointer
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// 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
|
||||
}
|
||||
|
||||
/// 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<U, F>(this: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where
|
||||
F: FnOnce(&mut T) -> &mut U,
|
||||
{
|
||||
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
|
||||
impl<P: Deref> Deref for Pin<P> {
|
||||
type Target = P::Target;
|
||||
fn deref(&self) -> &P::Target {
|
||||
Pin::get_ref(Pin::as_ref(self))
|
||||
}
|
||||
}
|
||||
|
||||
#[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>, U: ?Sized> CoerceUnsized<PinMut<'a, U>> 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<Output = T> + 'a
|
||||
impl<P: DerefMut> DerefMut for Pin<P>
|
||||
where
|
||||
P::Target: Unpin
|
||||
{
|
||||
fn into_raw(self) -> *mut () {
|
||||
unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () }
|
||||
fn deref_mut(&mut self) -> &mut P::Target {
|
||||
Pin::get_mut(Pin::as_mut(self))
|
||||
}
|
||||
|
||||
unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
|
||||
PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx)
|
||||
}
|
||||
|
||||
unsafe fn drop(_ptr: *mut ()) {}
|
||||
}
|
||||
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
impl<'a, P: fmt::Debug> fmt::Debug for Pin<P> {
|
||||
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<P> {
|
||||
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<P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Pointer::fmt(&self.pointer, f)
|
||||
}
|
||||
}
|
||||
|
||||
// Note: this means that any impl of `CoerceUnsized` that allows coercing from
|
||||
// a type that impls `Deref<Target=impl !Unpin>` to a type that impls
|
||||
// `Deref<Target=Unpin>` 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, P, U> CoerceUnsized<Pin<U>> for Pin<P>
|
||||
where
|
||||
P: CoerceUnsized<U>,
|
||||
{}
|
||||
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
impl<'a, P> Unpin for Pin<P> {}
|
||||
|
@ -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<T: Generator<Yield = ()>> !Unpin for GenFuture<T> {}
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
impl<T: Generator<Yield = ()>> Future for GenFuture<T> {
|
||||
type Output = T::Return;
|
||||
fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
|
||||
set_task_cx(cx, || match unsafe { PinMut::get_mut_unchecked(self).0.resume() } {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {
|
||||
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, R>(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>(f: PinMut<F>) -> Poll<F::Output>
|
||||
pub fn poll_in_task_cx<F>(f: Pin<&mut F>) -> Poll<F::Output>
|
||||
where
|
||||
F: Future
|
||||
{
|
||||
get_task_cx(|cx| f.poll(cx))
|
||||
get_task_cx(|cx| F::poll(f, cx))
|
||||
}
|
||||
|
@ -435,7 +435,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")]
|
||||
|
@ -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;
|
||||
|
@ -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<F> {
|
||||
type Output = F::Output;
|
||||
|
||||
fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output> {
|
||||
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<Self::Output> {
|
||||
let pinned_field = unsafe { Pin::map_unchecked_mut(self, |x| &mut x.0) };
|
||||
F::poll(pinned_field, cx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<Self>, cx: &mut Context) -> Poll<()> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<()> {
|
||||
if self.0 {
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
@ -148,16 +147,16 @@ fn test_future_yields_once_then_returns<F, Fut>(f: F)
|
||||
F: FnOnce(u8) -> Fut,
|
||||
Fut: Future<Output = u8>,
|
||||
{
|
||||
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() {
|
||||
|
@ -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<Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
// 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));
|
||||
}
|
||||
|
@ -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 <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.
|
||||
|
||||
// exact-check
|
||||
|
||||
const QUERY = 'pinbox::new';
|
||||
|
||||
const EXPECTED = {
|
||||
'others': [
|
||||
{ 'path': 'std::pin::PinBox', 'name': 'new' },
|
||||
{ 'path': 'alloc::pin::PinBox', 'name': 'new' },
|
||||
],
|
||||
};
|
@ -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' },
|
||||
],
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user