Skip to content

Commit 537ede4

Browse files
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
2 parents 30f1bab + e3c6e46 commit 537ede4

File tree

4 files changed

+59
-16
lines changed

4 files changed

+59
-16
lines changed

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
#![feature(const_int_pow)]
7979
#![feature(constctlz)]
8080
#![feature(const_panic)]
81+
#![feature(const_pin)]
8182
#![feature(const_fn_union)]
8283
#![feature(const_generics)]
8384
#![feature(const_option)]

library/core/src/pin.rs

+24-16
Original file line numberDiff line numberDiff line change
@@ -471,9 +471,10 @@ impl<P: Deref<Target: Unpin>> Pin<P> {
471471
///
472472
/// Unlike `Pin::new_unchecked`, this method is safe because the pointer
473473
/// `P` dereferences to an [`Unpin`] type, which cancels the pinning guarantees.
474-
#[stable(feature = "pin", since = "1.33.0")]
475474
#[inline(always)]
476-
pub fn new(pointer: P) -> Pin<P> {
475+
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
476+
#[stable(feature = "pin", since = "1.33.0")]
477+
pub const fn new(pointer: P) -> Pin<P> {
477478
// SAFETY: the value pointed to is `Unpin`, and so has no requirements
478479
// around pinning.
479480
unsafe { Pin::new_unchecked(pointer) }
@@ -483,9 +484,10 @@ impl<P: Deref<Target: Unpin>> Pin<P> {
483484
///
484485
/// This requires that the data inside this `Pin` is [`Unpin`] so that we
485486
/// can ignore the pinning invariants when unwrapping it.
486-
#[stable(feature = "pin_into_inner", since = "1.39.0")]
487487
#[inline(always)]
488-
pub fn into_inner(pin: Pin<P>) -> P {
488+
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
489+
#[stable(feature = "pin_into_inner", since = "1.39.0")]
490+
pub const fn into_inner(pin: Pin<P>) -> P {
489491
pin.pointer
490492
}
491493
}
@@ -556,9 +558,10 @@ impl<P: Deref> Pin<P> {
556558
///
557559
/// [`mem::swap`]: crate::mem::swap
558560
#[lang = "new_unchecked"]
559-
#[stable(feature = "pin", since = "1.33.0")]
560561
#[inline(always)]
561-
pub unsafe fn new_unchecked(pointer: P) -> Pin<P> {
562+
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
563+
#[stable(feature = "pin", since = "1.33.0")]
564+
pub const unsafe fn new_unchecked(pointer: P) -> Pin<P> {
562565
Pin { pointer }
563566
}
564567

@@ -589,9 +592,10 @@ impl<P: Deref> Pin<P> {
589592
///
590593
/// If the underlying data is [`Unpin`], [`Pin::into_inner`] should be used
591594
/// instead.
592-
#[stable(feature = "pin_into_inner", since = "1.39.0")]
593595
#[inline(always)]
594-
pub unsafe fn into_inner_unchecked(pin: Pin<P>) -> P {
596+
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
597+
#[stable(feature = "pin_into_inner", since = "1.39.0")]
598+
pub const unsafe fn into_inner_unchecked(pin: Pin<P>) -> P {
595599
pin.pointer
596600
}
597601
}
@@ -693,18 +697,20 @@ impl<'a, T: ?Sized> Pin<&'a T> {
693697
/// with the same lifetime as the original `Pin`.
694698
///
695699
/// ["pinning projections"]: self#projections-and-structural-pinning
696-
#[stable(feature = "pin", since = "1.33.0")]
697700
#[inline(always)]
698-
pub fn get_ref(self) -> &'a T {
701+
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
702+
#[stable(feature = "pin", since = "1.33.0")]
703+
pub const fn get_ref(self) -> &'a T {
699704
self.pointer
700705
}
701706
}
702707

703708
impl<'a, T: ?Sized> Pin<&'a mut T> {
704709
/// Converts this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime.
705-
#[stable(feature = "pin", since = "1.33.0")]
706710
#[inline(always)]
707-
pub fn into_ref(self) -> Pin<&'a T> {
711+
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
712+
#[stable(feature = "pin", since = "1.33.0")]
713+
pub const fn into_ref(self) -> Pin<&'a T> {
708714
Pin { pointer: self.pointer }
709715
}
710716

@@ -717,9 +723,10 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
717723
/// that lives for as long as the borrow of the `Pin`, not the lifetime of
718724
/// the `Pin` itself. This method allows turning the `Pin` into a reference
719725
/// with the same lifetime as the original `Pin`.
720-
#[stable(feature = "pin", since = "1.33.0")]
721726
#[inline(always)]
722-
pub fn get_mut(self) -> &'a mut T
727+
#[stable(feature = "pin", since = "1.33.0")]
728+
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
729+
pub const fn get_mut(self) -> &'a mut T
723730
where
724731
T: Unpin,
725732
{
@@ -736,9 +743,10 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
736743
///
737744
/// If the underlying data is `Unpin`, `Pin::get_mut` should be used
738745
/// instead.
739-
#[stable(feature = "pin", since = "1.33.0")]
740746
#[inline(always)]
741-
pub unsafe fn get_unchecked_mut(self) -> &'a mut T {
747+
#[stable(feature = "pin", since = "1.33.0")]
748+
#[rustc_const_unstable(feature = "const_pin", issue = "76654")]
749+
pub const unsafe fn get_unchecked_mut(self) -> &'a mut T {
742750
self.pointer
743751
}
744752

library/core/tests/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
#![feature(iter_order_by)]
4444
#![feature(cmp_min_max_by)]
4545
#![feature(iter_map_while)]
46+
#![feature(const_mut_refs)]
47+
#![feature(const_pin)]
4648
#![feature(const_slice_from_raw_parts)]
4749
#![feature(const_raw_ptr_deref)]
4850
#![feature(never_type)]
@@ -79,6 +81,7 @@ mod num;
7981
mod ops;
8082
mod option;
8183
mod pattern;
84+
mod pin;
8285
mod ptr;
8386
mod result;
8487
mod slice;

library/core/tests/pin.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use core::pin::Pin;
2+
3+
#[test]
4+
fn pin_const() {
5+
// test that the methods of `Pin` are usable in a const context
6+
7+
const POINTER: &'static usize = &2;
8+
9+
const PINNED: Pin<&'static usize> = Pin::new(POINTER);
10+
const PINNED_UNCHECKED: Pin<&'static usize> = unsafe { Pin::new_unchecked(POINTER) };
11+
assert_eq!(PINNED_UNCHECKED, PINNED);
12+
13+
const INNER: &'static usize = Pin::into_inner(PINNED);
14+
assert_eq!(INNER, POINTER);
15+
16+
const INNER_UNCHECKED: &'static usize = unsafe { Pin::into_inner_unchecked(PINNED) };
17+
assert_eq!(INNER_UNCHECKED, POINTER);
18+
19+
const REF: &'static usize = PINNED.get_ref();
20+
assert_eq!(REF, POINTER);
21+
22+
// Note: `pin_mut_const` tests that the methods of `Pin<&mut T>` are usable in a const context.
23+
// A const fn is used because `&mut` is not (yet) usable in constants.
24+
const fn pin_mut_const() {
25+
let _ = Pin::new(&mut 2).into_ref();
26+
let _ = Pin::new(&mut 2).get_mut();
27+
let _ = unsafe { Pin::new(&mut 2).get_unchecked_mut() };
28+
}
29+
30+
pin_mut_const();
31+
}

0 commit comments

Comments
 (0)