Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PinCoerceUnsized trait into core #125048

Merged
merged 1 commit into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ symbols! {
Path,
PathBuf,
Pending,
PinCoerceUnsized,
Pointer,
Poll,
ProcMacro,
Expand Down
5 changes: 4 additions & 1 deletion library/alloc/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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> {}
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
10 changes: 10 additions & 0 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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> {}

Expand Down Expand Up @@ -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 {
Expand Down
8 changes: 7 additions & 1 deletion library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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> {}

Expand Down
14 changes: 14 additions & 0 deletions library/alloc/tests/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
37 changes: 37 additions & 0 deletions library/alloc/tests/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}
1 change: 1 addition & 0 deletions library/alloc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
17 changes: 17 additions & 0 deletions library/alloc/tests/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
19 changes: 19 additions & 0 deletions library/core/src/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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> {}
50 changes: 48 additions & 2 deletions library/core/src/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Comment on lines +1754 to +1758
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should also implement for raw pointers and NonNull. (And add a test.)


#[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.
///
Expand Down
4 changes: 4 additions & 0 deletions library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions library/core/src/ptr/unique.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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 {
Expand Down
46 changes: 46 additions & 0 deletions library/core/tests/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
Expand Down
Loading