Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Cleanup and fix method resolution issue
  • Loading branch information
cramertj committed Sep 17, 2018
1 parent 974bdc8 commit 3ec1810
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 73 deletions.
6 changes: 5 additions & 1 deletion src/liballoc/boxed.rs
Expand Up @@ -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()
}
}

Expand Down Expand Up @@ -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) }
}
}
Expand Down
14 changes: 7 additions & 7 deletions src/libcore/future/future.rs
Expand Up @@ -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)
}
}
6 changes: 2 additions & 4 deletions src/libcore/option.rs
Expand Up @@ -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))
}
}

Expand All @@ -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))
}
}

Expand Down
142 changes: 93 additions & 49 deletions src/libcore/pin.rs
Expand Up @@ -7,15 +7,15 @@
//! 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
//! 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`],
//! 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.
//!
Expand All @@ -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
//!
Expand Down Expand Up @@ -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;
//! }
Expand All @@ -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
Expand All @@ -103,71 +106,78 @@ 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)]
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,
Expand All @@ -188,22 +198,57 @@ 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
///
/// 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
}
Expand All @@ -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
}
}
Expand All @@ -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> {}

#[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> {}
impl<'a, P, U> CoerceUnsized<Pin<U>> for Pin<P>
where
P: CoerceUnsized<U>,
{}

#[unstable(feature = "pin", issue = "49150")]
impl<'a, T: ?Sized> Unpin for Pin<&'a mut T> {}
impl<'a, P> Unpin for Pin<P> {}
11 changes: 5 additions & 6 deletions src/test/run-pass/async-await.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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() {
Expand Down

0 comments on commit 3ec1810

Please sign in to comment.