Cleanup and fix method resolution issue

This commit is contained in:
Taylor Cramer 2018-09-14 17:40:52 -07:00
parent 974bdc80fe
commit 3ec1810e32
6 changed files with 117 additions and 73 deletions

View file

@ -98,8 +98,9 @@ impl<T> Box<T> {
}
#[unstable(feature = "pin", issue = "49150")]
#[inline(always)]
pub fn pinned(x: T) -> Pin<Box<T>> {
unsafe { Pin::new_unchecked(box x) }
(box x).into()
}
}
@ -434,6 +435,9 @@ impl<T> From<T> for Box<T> {
#[unstable(feature = "pin", issue = "49150")]
impl<T> From<Box<T>> for Pin<Box<T>> {
fn from(boxed: Box<T>) -> Self {
// 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) }
}
}

View file

@ -104,14 +104,14 @@ impl<'a, F: ?Sized + Future + Unpin> Future for &'a mut F {
}
}
impl<P, F> Future for Pin<P> where
P: ops::DerefMut<Target = F> + Unpin,
F: Future + ?Sized,
impl<P> Future for Pin<P>
where
P: ops::DerefMut,
P::Target: Future,
{
type Output = F::Output;
type Output = <<P as ops::Deref>::Target as Future>::Output;
fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {
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<Self::Output> {
Pin::get_mut(self).as_mut().poll(cx)
}
}

View file

@ -276,8 +276,7 @@ impl<T> Option<T> {
#[unstable(feature = "pin", issue = "49150")]
pub fn as_pin_ref<'a>(self: Pin<&'a Option<T>>) -> Option<Pin<&'a T>> {
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 @@ impl<T> Option<T> {
#[unstable(feature = "pin", issue = "49150")]
pub fn as_pin_mut<'a>(self: Pin<&'a mut Option<T>>) -> Option<Pin<&'a mut T>> {
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))
}
}

View file

@ -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<Box<T>>`
//! and `Box<T>` 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 @@ use ops::{Deref, DerefMut, CoerceUnsized};
///
/// [`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<P> {
pointer: P,
}
impl<P, T> Pin<P> where
P: Deref<Target = T>,
T: ?Sized + Unpin,
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")]
#[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) }
}
}
impl<P, T> Pin<P> where
P: Deref<Target = T>,
T: ?Sized,
{
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`.
///
/// # Safety
///
/// This constructor is unsafe because we cannot guarantee that the target data
/// is properly pinned by this pointer. If the constructed `Pin<P>` does not guarantee
/// that the data is "pinned," constructing a `Pin<P>` 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<P>` does
/// not guarantee that the data `P` points to is pinned, constructing a
/// `Pin<P>` 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<P> {
Pin { pointer }
}
/// Get a pinned shared reference from this pinned pointer.
#[unstable(feature = "pin", issue = "49150")]
pub fn as_ref(this: &Pin<P>) -> Pin<&T> {
unsafe { Pin::new_unchecked(&**this) }
#[inline(always)]
pub fn as_ref(self: &Pin<P>) -> Pin<&P::Target> {
unsafe { Pin::new_unchecked(&**self) }
}
}
impl<P, T> Pin<P> where
P: DerefMut<Target = T>,
T: ?Sized,
{
impl<P: DerefMut> Pin<P> {
/// Get a pinned mutable reference from this pinned pointer.
#[unstable(feature = "pin", issue = "49150")]
pub fn as_mut(this: &mut Pin<P>) -> Pin<&mut T> {
unsafe { Pin::new_unchecked(&mut *this.pointer) }
#[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")]
pub fn set(this: Pin<&mut T>, value: T)
where T: Sized,
#[inline(always)]
pub fn set(mut self: Pin<P>, 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 @@ impl<'a, T> Pin<&'a T> {
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 @@ impl<'a, T> Pin<&'a mut T> {
}
#[unstable(feature = "pin", issue = "49150")]
impl<P, T> Deref for Pin<P> where
P: Deref<Target = T>,
T: ?Sized,
{
type Target = T;
fn deref(&self) -> &T {
impl<P: Deref> Deref for Pin<P> {
type Target = P::Target;
fn deref(&self) -> &P::Target {
&*self.pointer
}
}
#[unstable(feature = "pin", issue = "49150")]
impl<P, T> DerefMut for Pin<P> where
P: DerefMut<Target = T>,
T: ?Sized + Unpin,
impl<P: DerefMut> DerefMut for Pin<P>
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 @@ impl<'a, P: fmt::Pointer> fmt::Pointer for Pin<P> {
}
}
// 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, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Pin<&'a U>> for Pin<&'a T> {}
impl<'a, P, U> CoerceUnsized<Pin<U>> for Pin<P>
where
P: CoerceUnsized<U>,
{}
#[unstable(feature = "pin", issue = "49150")]
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Pin<&'a mut U>> 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<P> {}

View file

@ -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 {
@ -124,16 +123,16 @@ where
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() {

View file

@ -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 @@ struct MyFuture;
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));
}