about summary refs log tree commit diff
diff options
context:
space:
mode:
authorXiangfei Ding <dingxiangfei2009@protonmail.ch>2024-05-13 03:16:31 +0800
committerDing Xiang Fei <dingxiangfei2009@protonmail.ch>2024-07-31 17:10:55 +0800
commitd495b84a9a5a0bfcfe353c53b332664c7414e315 (patch)
tree9f7b10247eac5b9c6e6231e3744e2127c3246b49
parent83dcdb3a5dad0ed1e3e1fadc848d3f7727b41aa5 (diff)
downloadrust-d495b84a9a5a0bfcfe353c53b332664c7414e315.tar.gz
rust-d495b84a9a5a0bfcfe353c53b332664c7414e315.zip
PinCoerceUnsized trait into core
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/alloc/src/boxed.rs5
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/rc.rs10
-rw-r--r--library/alloc/src/sync.rs8
-rw-r--r--library/alloc/tests/arc.rs14
-rw-r--r--library/alloc/tests/boxed.rs37
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/rc.rs17
-rw-r--r--library/core/src/cell.rs19
-rw-r--r--library/core/src/pin.rs50
-rw-r--r--library/core/src/ptr/non_null.rs4
-rw-r--r--library/core/src/ptr/unique.rs4
-rw-r--r--library/core/tests/pin.rs46
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs4
16 files changed, 218 insertions, 4 deletions
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index e8563f50158..9bacb60eca9 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -276,6 +276,7 @@ symbols! {
         Path,
         PathBuf,
         Pending,
+        PinCoerceUnsized,
         Pointer,
         Poll,
         ProcMacro,
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index ef40d3b203f..4b8706a8426 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -200,7 +200,7 @@ use core::ops::{
     AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut,
     DerefPure, DispatchFromDyn, Receiver,
 };
-use core::pin::Pin;
+use core::pin::{Pin, PinCoerceUnsized};
 use core::ptr::{self, addr_of_mut, NonNull, Unique};
 use core::task::{Context, Poll};
 use core::{borrow, fmt, slice};
@@ -2724,3 +2724,6 @@ impl<T: core::error::Error> core::error::Error for Box<T> {
         core::error::Error::provide(&**self, request);
     }
 }
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Box<T, A> {}
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 28b08ef5611..3e44adf73f0 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -138,6 +138,7 @@
 #![feature(maybe_uninit_uninit_array_transpose)]
 #![feature(panic_internals)]
 #![feature(pattern)]
+#![feature(pin_coerce_unsized_trait)]
 #![feature(ptr_internals)]
 #![feature(ptr_metadata)]
 #![feature(ptr_sub_ptr)]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index bc0874fc13f..9352af99cdd 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -256,6 +256,7 @@ use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Rece
 use core::panic::{RefUnwindSafe, UnwindSafe};
 #[cfg(not(no_global_oom_handling))]
 use core::pin::Pin;
+use core::pin::PinCoerceUnsized;
 use core::ptr::{self, drop_in_place, NonNull};
 #[cfg(not(no_global_oom_handling))]
 use core::slice::from_raw_parts_mut;
@@ -2176,6 +2177,12 @@ impl<T: ?Sized, A: Allocator> Deref for Rc<T, A> {
     }
 }
 
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Rc<T, A> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
+
 #[unstable(feature = "deref_pure_trait", issue = "87121")]
 unsafe impl<T: ?Sized, A: Allocator> DerefPure for Rc<T, A> {}
 
@@ -3689,6 +3696,9 @@ impl<T: ?Sized, A: Allocator> Deref for UniqueRc<T, A> {
     }
 }
 
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for UniqueRc<T> {}
+
 #[unstable(feature = "unique_rc_arc", issue = "112566")]
 impl<T: ?Sized, A: Allocator> DerefMut for UniqueRc<T, A> {
     fn deref_mut(&mut self) -> &mut T {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 3ad0dae77db..2c0d19b0ada 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -20,7 +20,7 @@ use core::marker::{PhantomData, Unsize};
 use core::mem::{self, align_of_val_raw, ManuallyDrop};
 use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver};
 use core::panic::{RefUnwindSafe, UnwindSafe};
-use core::pin::Pin;
+use core::pin::{Pin, PinCoerceUnsized};
 use core::ptr::{self, NonNull};
 #[cfg(not(no_global_oom_handling))]
 use core::slice::from_raw_parts_mut;
@@ -2142,6 +2142,12 @@ impl<T: ?Sized, A: Allocator> Deref for Arc<T, A> {
     }
 }
 
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Arc<T, A> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
+
 #[unstable(feature = "deref_pure_trait", issue = "87121")]
 unsafe impl<T: ?Sized, A: Allocator> DerefPure for Arc<T, A> {}
 
diff --git a/library/alloc/tests/arc.rs b/library/alloc/tests/arc.rs
index c37a80dca95..dc27c578b57 100644
--- a/library/alloc/tests/arc.rs
+++ b/library/alloc/tests/arc.rs
@@ -227,3 +227,17 @@ fn make_mut_unsized() {
     assert_eq!(*data, [11, 21, 31]);
     assert_eq!(*other_data, [110, 20, 30]);
 }
+
+#[allow(unused)]
+mod pin_coerce_unsized {
+    use alloc::sync::Arc;
+    use core::pin::Pin;
+
+    pub trait MyTrait {}
+    impl MyTrait for String {}
+
+    // Pin coercion should work for Arc
+    pub fn pin_arc(arg: Pin<Arc<String>>) -> Pin<Arc<dyn MyTrait>> {
+        arg
+    }
+}
diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs
index 4cacee0414d..faee64b2f67 100644
--- a/library/alloc/tests/boxed.rs
+++ b/library/alloc/tests/boxed.rs
@@ -179,3 +179,40 @@ unsafe impl Allocator for ConstAllocator {
         self
     }
 }
+
+#[allow(unused)]
+mod pin_coerce_unsized {
+    use alloc::boxed::Box;
+    use core::pin::Pin;
+
+    trait MyTrait {
+        fn action(&self) -> &str;
+    }
+    impl MyTrait for String {
+        fn action(&self) -> &str {
+            &*self
+        }
+    }
+    struct MyStruct;
+    impl MyTrait for MyStruct {
+        fn action(&self) -> &str {
+            "MyStruct"
+        }
+    }
+
+    // Pin coercion should work for Box
+    fn pin_box<T: MyTrait + 'static>(arg: Pin<Box<T>>) -> Pin<Box<dyn MyTrait>> {
+        arg
+    }
+
+    #[test]
+    fn pin_coerce_unsized_box() {
+        let my_string = "my string";
+        let a_string = Box::pin(String::from(my_string));
+        let pin_box_str = pin_box(a_string);
+        assert_eq!(pin_box_str.as_ref().action(), my_string);
+        let a_struct = Box::pin(MyStruct);
+        let pin_box_struct = pin_box(a_struct);
+        assert_eq!(pin_box_struct.as_ref().action(), "MyStruct");
+    }
+}
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 89538f272f0..3d4add6fae4 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -40,6 +40,7 @@
 #![feature(drain_keep_rest)]
 #![feature(local_waker)]
 #![feature(vec_pop_if)]
+#![feature(unique_rc_arc)]
 #![allow(internal_features)]
 #![deny(fuzzy_provenance_casts)]
 #![deny(unsafe_op_in_unsafe_fn)]
diff --git a/library/alloc/tests/rc.rs b/library/alloc/tests/rc.rs
index 499740e738a..29dbdcf225e 100644
--- a/library/alloc/tests/rc.rs
+++ b/library/alloc/tests/rc.rs
@@ -205,3 +205,20 @@ fn weak_may_dangle() {
     // `val` dropped here while still borrowed
     // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::rc::Weak`
 }
+
+#[allow(unused)]
+mod pin_coerce_unsized {
+    use alloc::rc::{Rc, UniqueRc};
+    use core::pin::Pin;
+
+    pub trait MyTrait {}
+    impl MyTrait for String {}
+
+    // Pin coercion should work for Rc
+    pub fn pin_rc(arg: Pin<Rc<String>>) -> Pin<Rc<dyn MyTrait>> {
+        arg
+    }
+    pub fn pin_unique_rc(arg: Pin<UniqueRc<String>>) -> Pin<UniqueRc<dyn MyTrait>> {
+        arg
+    }
+}
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 0d66c2b52c8..d860f3415d9 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -255,6 +255,7 @@ use crate::fmt::{self, Debug, Display};
 use crate::marker::{PhantomData, Unsize};
 use crate::mem;
 use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
+use crate::pin::PinCoerceUnsized;
 use crate::ptr::{self, NonNull};
 
 mod lazy;
@@ -2396,3 +2397,21 @@ fn assert_coerce_unsized(
     let _: Cell<&dyn Send> = c;
     let _: RefCell<&dyn Send> = d;
 }
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for UnsafeCell<T> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for SyncUnsafeCell<T> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for Cell<T> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for RefCell<T> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<'b, T: ?Sized> PinCoerceUnsized for Ref<'b, T> {}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<'b, T: ?Sized> PinCoerceUnsized for RefMut<'b, T> {}
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index d752151d10c..0569b8b7624 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1715,10 +1715,56 @@ impl<Ptr: fmt::Pointer> fmt::Pointer for Pin<Ptr> {
 // for other reasons, though, so we just need to take care not to allow such
 // impls to land in std.
 #[stable(feature = "pin", since = "1.33.0")]
-impl<Ptr, U> CoerceUnsized<Pin<U>> for Pin<Ptr> where Ptr: CoerceUnsized<U> {}
+impl<Ptr, U> CoerceUnsized<Pin<U>> for Pin<Ptr>
+where
+    Ptr: CoerceUnsized<U> + PinCoerceUnsized,
+    U: PinCoerceUnsized,
+{
+}
+
+#[stable(feature = "pin", since = "1.33.0")]
+impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr>
+where
+    Ptr: DispatchFromDyn<U> + PinCoerceUnsized,
+    U: PinCoerceUnsized,
+{
+}
+
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+/// Trait that indicates that this is a pointer or a wrapper for one, where
+/// unsizing can be performed on the pointee when it is pinned.
+///
+/// # Safety
+///
+/// If this type implements `Deref`, then the concrete type returned by `deref`
+/// and `deref_mut` must not change without a modification. The following
+/// operations are not considered modifications:
+///
+/// * Moving the pointer.
+/// * Performing unsizing coercions on the pointer.
+/// * Performing dynamic dispatch with the pointer.
+/// * Calling `deref` or `deref_mut` on the pointer.
+///
+/// The concrete type of a trait object is the type that the vtable corresponds
+/// to. The concrete type of a slice is an array of the same element type and
+/// the length specified in the metadata. The concrete type of a sized type
+/// is the type itself.
+pub unsafe trait PinCoerceUnsized {}
+
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a T {}
+
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a mut T {}
+
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<T: PinCoerceUnsized> PinCoerceUnsized for Pin<T> {}
+
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for *const T {}
 
 #[stable(feature = "pin", since = "1.33.0")]
-impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr> where Ptr: DispatchFromDyn<U> {}
+unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
 
 /// Constructs a <code>[Pin]<[&mut] T></code>, by pinning a `value: T` locally.
 ///
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 4a716a75039..44db227b79e 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -3,6 +3,7 @@ use crate::marker::Unsize;
 use crate::mem::{MaybeUninit, SizedTypeProperties};
 use crate::num::NonZero;
 use crate::ops::{CoerceUnsized, DispatchFromDyn};
+use crate::pin::PinCoerceUnsized;
 use crate::ptr::Unique;
 use crate::slice::{self, SliceIndex};
 use crate::ub_checks::assert_unsafe_precondition;
@@ -1724,6 +1725,9 @@ impl<T: ?Sized, U: ?Sized> CoerceUnsized<NonNull<U>> for NonNull<T> where T: Uns
 #[unstable(feature = "dispatch_from_dyn", issue = "none")]
 impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
 
+#[stable(feature = "pin", since = "1.33.0")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for NonNull<T> {}
+
 #[stable(feature = "nonnull", since = "1.25.0")]
 impl<T: ?Sized> fmt::Debug for NonNull<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs
index b74d691e454..4810ebe01f9 100644
--- a/library/core/src/ptr/unique.rs
+++ b/library/core/src/ptr/unique.rs
@@ -1,6 +1,7 @@
 use crate::fmt;
 use crate::marker::{PhantomData, Unsize};
 use crate::ops::{CoerceUnsized, DispatchFromDyn};
+use crate::pin::PinCoerceUnsized;
 use crate::ptr::NonNull;
 
 /// A wrapper around a raw non-null `*mut T` that indicates that the possessor
@@ -166,6 +167,9 @@ impl<T: ?Sized, U: ?Sized> CoerceUnsized<Unique<U>> for Unique<T> where T: Unsiz
 #[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
 
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for Unique<T> {}
+
 #[unstable(feature = "ptr_internals", issue = "none")]
 impl<T: ?Sized> fmt::Debug for Unique<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/core/tests/pin.rs b/library/core/tests/pin.rs
index 6f617c8d0c2..7a6af46a743 100644
--- a/library/core/tests/pin.rs
+++ b/library/core/tests/pin.rs
@@ -29,3 +29,49 @@ fn pin_const() {
 
     pin_mut_const();
 }
+
+#[allow(unused)]
+mod pin_coerce_unsized {
+    use core::cell::{Cell, RefCell, UnsafeCell};
+    use core::pin::Pin;
+    use core::ptr::NonNull;
+
+    pub trait MyTrait {}
+    impl MyTrait for String {}
+
+    // These Pins should continue to compile.
+    // Do note that these instances of Pin types cannot be used
+    // meaningfully because all methods require a Deref/DerefMut
+    // bounds on the pointer type and Cell, RefCell and UnsafeCell
+    // do not implement Deref/DerefMut.
+
+    pub fn cell(arg: Pin<Cell<Box<String>>>) -> Pin<Cell<Box<dyn MyTrait>>> {
+        arg
+    }
+    pub fn ref_cell(arg: Pin<RefCell<Box<String>>>) -> Pin<RefCell<Box<dyn MyTrait>>> {
+        arg
+    }
+    pub fn unsafe_cell(arg: Pin<UnsafeCell<Box<String>>>) -> Pin<UnsafeCell<Box<dyn MyTrait>>> {
+        arg
+    }
+
+    // These sensible Pin coercions are possible.
+    pub fn pin_mut_ref(arg: Pin<&mut String>) -> Pin<&mut dyn MyTrait> {
+        arg
+    }
+    pub fn pin_ref(arg: Pin<&String>) -> Pin<&dyn MyTrait> {
+        arg
+    }
+    pub fn pin_ptr(arg: Pin<*const String>) -> Pin<*const dyn MyTrait> {
+        arg
+    }
+    pub fn pin_ptr_mut(arg: Pin<*mut String>) -> Pin<*mut dyn MyTrait> {
+        arg
+    }
+    pub fn pin_non_null(arg: Pin<NonNull<String>>) -> Pin<NonNull<dyn MyTrait>> {
+        arg
+    }
+    pub fn nesting_pins(arg: Pin<Pin<&String>>) -> Pin<Pin<&dyn MyTrait>> {
+        arg
+    }
+}
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 6bd9c59a949..58d3c4a994b 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -342,6 +342,7 @@
 #![feature(maybe_uninit_write_slice)]
 #![feature(panic_can_unwind)]
 #![feature(panic_internals)]
+#![feature(pin_coerce_unsized_trait)]
 #![feature(pointer_is_aligned_to)]
 #![feature(portable_simd)]
 #![feature(prelude_2024)]
diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
index 29809525739..5069ab82ccc 100644
--- a/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
+++ b/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
@@ -8,6 +8,7 @@ use crate::cell::UnsafeCell;
 use crate::convert::TryInto;
 use crate::mem::{self, ManuallyDrop};
 use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut};
+use crate::pin::PinCoerceUnsized;
 use crate::ptr::{self, NonNull};
 use crate::slice::SliceIndex;
 use crate::{cmp, intrinsics, slice};
@@ -751,6 +752,9 @@ where
 #[unstable(feature = "sgx_platform", issue = "56975")]
 impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
 
+#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
+unsafe impl<T: ?Sized> PinCoerceUnsized for UserRef<T> {}
+
 #[unstable(feature = "sgx_platform", issue = "56975")]
 impl<T, I> Index<I> for UserRef<[T]>
 where