about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorTaylor Cramer <cramertj@google.com>2018-09-14 17:40:52 -0700
committerTaylor Cramer <cramertj@google.com>2018-09-17 16:31:33 -0700
commit3ec1810e329bb9dfa0cf0686bdc13558771785d2 (patch)
treebb9f39ea9e7c740e1b8635f77868b3948a1e5b99 /src/libcore
parent974bdc80fe3214159dc30e0bbb76694900e613c0 (diff)
downloadrust-3ec1810e329bb9dfa0cf0686bdc13558771785d2.tar.gz
rust-3ec1810e329bb9dfa0cf0686bdc13558771785d2.zip
Cleanup and fix method resolution issue
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/future/future.rs14
-rw-r--r--src/libcore/option.rs6
-rw-r--r--src/libcore/pin.rs142
3 files changed, 102 insertions, 60 deletions
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 @@ 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)
     }
 }
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 @@ 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))
         }
     }
 
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<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> {}
-
-#[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> {}