about summary refs log tree commit diff
diff options
context:
space:
mode:
authorecstatic-morse <ecstaticmorse@gmail.com>2020-09-21 20:40:49 -0700
committerGitHub <noreply@github.com>2020-09-21 20:40:49 -0700
commit537ede465f25c80c99286aa7eb79a5295f345bc0 (patch)
tree222beb8230abb27c65d75a3a984368dfdb63b0b7
parent30f1bab7e6282a8e5ab644be15d12d5a5ca26e37 (diff)
parente3c6e46168758642f0bab64da374f93ed21b1cd0 (diff)
downloadrust-537ede465f25c80c99286aa7eb79a5295f345bc0.tar.gz
rust-537ede465f25c80c99286aa7eb79a5295f345bc0.zip
Rollup merge of #76655 - CDirkx:const-pin, r=ecstatic-morse
Make some methods of `Pin` unstable const

Make the following methods unstable const under the `const_pin` feature:
- `new`
- `new_unchecked`
- `into_inner`
- `into_inner_unchecked`
- `get_ref`
- `into_ref`
- `get_mut`
- `get_unchecked_mut`

Of these, `into_inner` and `into_inner_unchecked` require the unstable `const_precise_live_drops`.

Also adds tests for these methods in a const context.

Tracking issue: #76654

r? @ecstatic-morse
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/pin.rs40
-rw-r--r--library/core/tests/lib.rs3
-rw-r--r--library/core/tests/pin.rs31
4 files changed, 59 insertions, 16 deletions
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index fc6d6bcecd7..9de0f76cbdd 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -78,6 +78,7 @@
 #![feature(const_int_pow)]
 #![feature(constctlz)]
 #![feature(const_panic)]
+#![feature(const_pin)]
 #![feature(const_fn_union)]
 #![feature(const_generics)]
 #![feature(const_option)]
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 1cc1dfb0143..9f0284d5d95 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -471,9 +471,10 @@ impl<P: Deref<Target: Unpin>> Pin<P> {
     ///
     /// Unlike `Pin::new_unchecked`, this method is safe because the pointer
     /// `P` dereferences to an [`Unpin`] type, which cancels the pinning guarantees.
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn new(pointer: P) -> Pin<P> {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin", since = "1.33.0")]
+    pub const 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) }
@@ -483,9 +484,10 @@ impl<P: Deref<Target: Unpin>> Pin<P> {
     ///
     /// This requires that the data inside this `Pin` is [`Unpin`] so that we
     /// can ignore the pinning invariants when unwrapping it.
-    #[stable(feature = "pin_into_inner", since = "1.39.0")]
     #[inline(always)]
-    pub fn into_inner(pin: Pin<P>) -> P {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin_into_inner", since = "1.39.0")]
+    pub const fn into_inner(pin: Pin<P>) -> P {
         pin.pointer
     }
 }
@@ -556,9 +558,10 @@ impl<P: Deref> Pin<P> {
     ///
     /// [`mem::swap`]: crate::mem::swap
     #[lang = "new_unchecked"]
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub unsafe fn new_unchecked(pointer: P) -> Pin<P> {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin", since = "1.33.0")]
+    pub const unsafe fn new_unchecked(pointer: P) -> Pin<P> {
         Pin { pointer }
     }
 
@@ -589,9 +592,10 @@ impl<P: Deref> Pin<P> {
     ///
     /// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used
     /// instead.
-    #[stable(feature = "pin_into_inner", since = "1.39.0")]
     #[inline(always)]
-    pub unsafe fn into_inner_unchecked(pin: Pin<P>) -> P {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin_into_inner", since = "1.39.0")]
+    pub const unsafe fn into_inner_unchecked(pin: Pin<P>) -> P {
         pin.pointer
     }
 }
@@ -693,18 +697,20 @@ impl<'a, T: ?Sized> Pin<&'a T> {
     /// with the same lifetime as the original `Pin`.
     ///
     /// ["pinning projections"]: self#projections-and-structural-pinning
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn get_ref(self) -> &'a T {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin", since = "1.33.0")]
+    pub const fn get_ref(self) -> &'a T {
         self.pointer
     }
 }
 
 impl<'a, T: ?Sized> Pin<&'a mut T> {
     /// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn into_ref(self) -> Pin<&'a T> {
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    #[stable(feature = "pin", since = "1.33.0")]
+    pub const fn into_ref(self) -> Pin<&'a T> {
         Pin { pointer: self.pointer }
     }
 
@@ -717,9 +723,10 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
     /// 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`.
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub fn get_mut(self) -> &'a mut T
+    #[stable(feature = "pin", since = "1.33.0")]
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    pub const fn get_mut(self) -> &'a mut T
     where
         T: Unpin,
     {
@@ -736,9 +743,10 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
     ///
     /// If the underlying data is `Unpin`, `Pin::get_mut` should be used
     /// instead.
-    #[stable(feature = "pin", since = "1.33.0")]
     #[inline(always)]
-    pub unsafe fn get_unchecked_mut(self) -> &'a mut T {
+    #[stable(feature = "pin", since = "1.33.0")]
+    #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
+    pub const unsafe fn get_unchecked_mut(self) -> &'a mut T {
         self.pointer
     }
 
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 4db391f3e56..7e75c7cf47b 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -43,6 +43,8 @@
 #![feature(iter_order_by)]
 #![feature(cmp_min_max_by)]
 #![feature(iter_map_while)]
+#![feature(const_mut_refs)]
+#![feature(const_pin)]
 #![feature(const_slice_from_raw_parts)]
 #![feature(const_raw_ptr_deref)]
 #![feature(never_type)]
@@ -79,6 +81,7 @@ mod num;
 mod ops;
 mod option;
 mod pattern;
+mod pin;
 mod ptr;
 mod result;
 mod slice;
diff --git a/library/core/tests/pin.rs b/library/core/tests/pin.rs
new file mode 100644
index 00000000000..6f617c8d0c2
--- /dev/null
+++ b/library/core/tests/pin.rs
@@ -0,0 +1,31 @@
+use core::pin::Pin;
+
+#[test]
+fn pin_const() {
+    // test that the methods of `Pin` are usable in a const context
+
+    const POINTER: &'static usize = &2;
+
+    const PINNED: Pin<&'static usize> = Pin::new(POINTER);
+    const PINNED_UNCHECKED: Pin<&'static usize> = unsafe { Pin::new_unchecked(POINTER) };
+    assert_eq!(PINNED_UNCHECKED, PINNED);
+
+    const INNER: &'static usize = Pin::into_inner(PINNED);
+    assert_eq!(INNER, POINTER);
+
+    const INNER_UNCHECKED: &'static usize = unsafe { Pin::into_inner_unchecked(PINNED) };
+    assert_eq!(INNER_UNCHECKED, POINTER);
+
+    const REF: &'static usize = PINNED.get_ref();
+    assert_eq!(REF, POINTER);
+
+    // Note: `pin_mut_const` tests that the methods of `Pin<&mut T>` are usable in a const context.
+    // A const fn is used because `&mut` is not (yet) usable in constants.
+    const fn pin_mut_const() {
+        let _ = Pin::new(&mut 2).into_ref();
+        let _ = Pin::new(&mut 2).get_mut();
+        let _ = unsafe { Pin::new(&mut 2).get_unchecked_mut() };
+    }
+
+    pin_mut_const();
+}