diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 94cf21da4ef..32fca6733bb 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 38f50955b12..7de41259599 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}; @@ -2726,3 +2726,6 @@ impl core::error::Error for Box { core::error::Error::provide(&**self, request); } } + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Box {} 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 13d218e43a7..bdee06154fa 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; @@ -2177,6 +2178,12 @@ impl Deref for Rc { } } +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Rc {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Weak {} + #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for Rc {} @@ -3691,6 +3698,9 @@ impl Deref for UniqueRc { } } +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for UniqueRc {} + #[unstable(feature = "unique_rc_arc", issue = "112566")] impl DerefMut for UniqueRc { 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 Deref for Arc { } } +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Arc {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Weak {} + #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for Arc {} 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>) -> Pin> { + 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(arg: Pin>) -> Pin> { + 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>) -> Pin> { + arg + } + pub fn pin_unique_rc(arg: Pin>) -> Pin> { + 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 PinCoerceUnsized for UnsafeCell {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for SyncUnsafeCell {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Cell {} + +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for RefCell {} + +#[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 fmt::Pointer for Pin { // 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 CoerceUnsized> for Pin where Ptr: CoerceUnsized {} +impl CoerceUnsized> for Pin +where + Ptr: CoerceUnsized + PinCoerceUnsized, + U: PinCoerceUnsized, +{ +} #[stable(feature = "pin", since = "1.33.0")] -impl DispatchFromDyn> for Pin where Ptr: DispatchFromDyn {} +impl DispatchFromDyn> for Pin +where + Ptr: DispatchFromDyn + 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 PinCoerceUnsized for Pin {} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl PinCoerceUnsized for *const T {} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl PinCoerceUnsized for *mut T {} /// Constructs a [Pin]<[&mut] T>, 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 CoerceUnsized> for NonNull where T: Uns #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl DispatchFromDyn> for NonNull where T: Unsize {} +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl PinCoerceUnsized for NonNull {} + #[stable(feature = "nonnull", since = "1.25.0")] impl fmt::Debug for NonNull { 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 CoerceUnsized> for Unique where T: Unsiz #[unstable(feature = "ptr_internals", issue = "none")] impl DispatchFromDyn> for Unique where T: Unsize {} +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for Unique {} + #[unstable(feature = "ptr_internals", issue = "none")] impl fmt::Debug for Unique { 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>>) -> Pin>> { + arg + } + pub fn ref_cell(arg: Pin>>) -> Pin>> { + arg + } + pub fn unsafe_cell(arg: Pin>>) -> Pin>> { + 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>) -> Pin> { + arg + } + pub fn nesting_pins(arg: Pin>) -> Pin> { + arg + } +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 05e33d47bac..67405d788bd 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -339,6 +339,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, U> CoerceUnsized> for UserRef {} +#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")] +unsafe impl PinCoerceUnsized for UserRef {} + #[unstable(feature = "sgx_platform", issue = "56975")] impl Index for UserRef<[T]> where