Skip to content

Commit 449deaf

Browse files
PinCoerceUnsized trait into core
1 parent f8060d2 commit 449deaf

File tree

15 files changed

+216
-4
lines changed

15 files changed

+216
-4
lines changed

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ symbols! {
276276
Path,
277277
PathBuf,
278278
Pending,
279+
PinCoerceUnsized,
279280
Pointer,
280281
Poll,
281282
ProcMacro,

library/alloc/src/boxed.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ use core::ops::{
200200
AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut,
201201
DerefPure, DispatchFromDyn, Receiver,
202202
};
203-
use core::pin::Pin;
203+
use core::pin::{Pin, PinCoerceUnsized};
204204
use core::ptr::{self, addr_of_mut, NonNull, Unique};
205205
use core::task::{Context, Poll};
206206
use core::{borrow, fmt, slice};
@@ -2724,3 +2724,6 @@ impl<T: core::error::Error> core::error::Error for Box<T> {
27242724
core::error::Error::provide(&**self, request);
27252725
}
27262726
}
2727+
2728+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2729+
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Box<T, A> {}

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
#![feature(maybe_uninit_uninit_array_transpose)]
139139
#![feature(panic_internals)]
140140
#![feature(pattern)]
141+
#![feature(pin_coerce_unsized_trait)]
141142
#![feature(ptr_internals)]
142143
#![feature(ptr_metadata)]
143144
#![feature(ptr_sub_ptr)]

library/alloc/src/rc.rs

+10
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Rece
256256
use core::panic::{RefUnwindSafe, UnwindSafe};
257257
#[cfg(not(no_global_oom_handling))]
258258
use core::pin::Pin;
259+
use core::pin::PinCoerceUnsized;
259260
use core::ptr::{self, drop_in_place, NonNull};
260261
#[cfg(not(no_global_oom_handling))]
261262
use core::slice::from_raw_parts_mut;
@@ -2176,6 +2177,12 @@ impl<T: ?Sized, A: Allocator> Deref for Rc<T, A> {
21762177
}
21772178
}
21782179

2180+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2181+
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Rc<T, A> {}
2182+
2183+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2184+
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
2185+
21792186
#[unstable(feature = "deref_pure_trait", issue = "87121")]
21802187
unsafe impl<T: ?Sized, A: Allocator> DerefPure for Rc<T, A> {}
21812188

@@ -3689,6 +3696,9 @@ impl<T: ?Sized, A: Allocator> Deref for UniqueRc<T, A> {
36893696
}
36903697
}
36913698

3699+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
3700+
unsafe impl<T: ?Sized> PinCoerceUnsized for UniqueRc<T> {}
3701+
36923702
#[unstable(feature = "unique_rc_arc", issue = "112566")]
36933703
impl<T: ?Sized, A: Allocator> DerefMut for UniqueRc<T, A> {
36943704
fn deref_mut(&mut self) -> &mut T {

library/alloc/src/sync.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use core::marker::{PhantomData, Unsize};
2020
use core::mem::{self, align_of_val_raw, ManuallyDrop};
2121
use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver};
2222
use core::panic::{RefUnwindSafe, UnwindSafe};
23-
use core::pin::Pin;
23+
use core::pin::{Pin, PinCoerceUnsized};
2424
use core::ptr::{self, NonNull};
2525
#[cfg(not(no_global_oom_handling))]
2626
use core::slice::from_raw_parts_mut;
@@ -2142,6 +2142,12 @@ impl<T: ?Sized, A: Allocator> Deref for Arc<T, A> {
21422142
}
21432143
}
21442144

2145+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2146+
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Arc<T, A> {}
2147+
2148+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2149+
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Weak<T, A> {}
2150+
21452151
#[unstable(feature = "deref_pure_trait", issue = "87121")]
21462152
unsafe impl<T: ?Sized, A: Allocator> DerefPure for Arc<T, A> {}
21472153

library/alloc/tests/arc.rs

+14
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,17 @@ fn make_mut_unsized() {
227227
assert_eq!(*data, [11, 21, 31]);
228228
assert_eq!(*other_data, [110, 20, 30]);
229229
}
230+
231+
#[allow(unused)]
232+
mod pin_coerce_unsized {
233+
use alloc::sync::Arc;
234+
use core::pin::Pin;
235+
236+
pub trait MyTrait {}
237+
impl MyTrait for String {}
238+
239+
// Pin coercion should work for Arc
240+
pub fn pin_arc(arg: Pin<Arc<String>>) -> Pin<Arc<dyn MyTrait>> {
241+
arg
242+
}
243+
}

library/alloc/tests/boxed.rs

+37
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,40 @@ unsafe impl Allocator for ConstAllocator {
179179
self
180180
}
181181
}
182+
183+
#[allow(unused)]
184+
mod pin_coerce_unsized {
185+
use alloc::boxed::Box;
186+
use core::pin::Pin;
187+
188+
trait MyTrait {
189+
fn action(&self) -> &str;
190+
}
191+
impl MyTrait for String {
192+
fn action(&self) -> &str {
193+
&*self
194+
}
195+
}
196+
struct MyStruct;
197+
impl MyTrait for MyStruct {
198+
fn action(&self) -> &str {
199+
"MyStruct"
200+
}
201+
}
202+
203+
// Pin coercion should work for Box
204+
fn pin_box<T: MyTrait + 'static>(arg: Pin<Box<T>>) -> Pin<Box<dyn MyTrait>> {
205+
arg
206+
}
207+
208+
#[test]
209+
fn pin_coerce_unsized_box() {
210+
let my_string = "my string";
211+
let a_string = Box::pin(String::from(my_string));
212+
let pin_box_str = pin_box(a_string);
213+
assert_eq!(pin_box_str.as_ref().action(), my_string);
214+
let a_struct = Box::pin(MyStruct);
215+
let pin_box_struct = pin_box(a_struct);
216+
assert_eq!(pin_box_struct.as_ref().action(), "MyStruct");
217+
}
218+
}

library/alloc/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#![feature(drain_keep_rest)]
4141
#![feature(local_waker)]
4242
#![feature(vec_pop_if)]
43+
#![feature(unique_rc_arc)]
4344
#![allow(internal_features)]
4445
#![deny(fuzzy_provenance_casts)]
4546
#![deny(unsafe_op_in_unsafe_fn)]

library/alloc/tests/rc.rs

+17
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,20 @@ fn weak_may_dangle() {
205205
// `val` dropped here while still borrowed
206206
// borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::rc::Weak`
207207
}
208+
209+
#[allow(unused)]
210+
mod pin_coerce_unsized {
211+
use alloc::rc::{Rc, UniqueRc};
212+
use core::pin::Pin;
213+
214+
pub trait MyTrait {}
215+
impl MyTrait for String {}
216+
217+
// Pin coercion should work for Rc
218+
pub fn pin_rc(arg: Pin<Rc<String>>) -> Pin<Rc<dyn MyTrait>> {
219+
arg
220+
}
221+
pub fn pin_unique_rc(arg: Pin<UniqueRc<String>>) -> Pin<UniqueRc<dyn MyTrait>> {
222+
arg
223+
}
224+
}

library/core/src/cell.rs

+19
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ use crate::fmt::{self, Debug, Display};
255255
use crate::marker::{PhantomData, Unsize};
256256
use crate::mem;
257257
use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
258+
use crate::pin::PinCoerceUnsized;
258259
use crate::ptr::{self, NonNull};
259260

260261
mod lazy;
@@ -2396,3 +2397,21 @@ fn assert_coerce_unsized(
23962397
let _: Cell<&dyn Send> = c;
23972398
let _: RefCell<&dyn Send> = d;
23982399
}
2400+
2401+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2402+
unsafe impl<T: ?Sized> PinCoerceUnsized for UnsafeCell<T> {}
2403+
2404+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2405+
unsafe impl<T: ?Sized> PinCoerceUnsized for SyncUnsafeCell<T> {}
2406+
2407+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2408+
unsafe impl<T: ?Sized> PinCoerceUnsized for Cell<T> {}
2409+
2410+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2411+
unsafe impl<T: ?Sized> PinCoerceUnsized for RefCell<T> {}
2412+
2413+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2414+
unsafe impl<'b, T: ?Sized> PinCoerceUnsized for Ref<'b, T> {}
2415+
2416+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2417+
unsafe impl<'b, T: ?Sized> PinCoerceUnsized for RefMut<'b, T> {}

library/core/src/pin.rs

+48-2
Original file line numberDiff line numberDiff line change
@@ -1715,10 +1715,56 @@ impl<Ptr: fmt::Pointer> fmt::Pointer for Pin<Ptr> {
17151715
// for other reasons, though, so we just need to take care not to allow such
17161716
// impls to land in std.
17171717
#[stable(feature = "pin", since = "1.33.0")]
1718-
impl<Ptr, U> CoerceUnsized<Pin<U>> for Pin<Ptr> where Ptr: CoerceUnsized<U> {}
1718+
impl<Ptr, U> CoerceUnsized<Pin<U>> for Pin<Ptr>
1719+
where
1720+
Ptr: CoerceUnsized<U> + PinCoerceUnsized,
1721+
U: PinCoerceUnsized,
1722+
{
1723+
}
1724+
1725+
#[stable(feature = "pin", since = "1.33.0")]
1726+
impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr>
1727+
where
1728+
Ptr: DispatchFromDyn<U> + PinCoerceUnsized,
1729+
U: PinCoerceUnsized,
1730+
{
1731+
}
1732+
1733+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
1734+
/// Trait that indicates that this is a pointer or a wrapper for one, where
1735+
/// unsizing can be performed on the pointee when it is pinned.
1736+
///
1737+
/// # Safety
1738+
///
1739+
/// If this type implements `Deref`, then the concrete type returned by `deref`
1740+
/// and `deref_mut` must not change without a modification. The following
1741+
/// operations are not considered modifications:
1742+
///
1743+
/// * Moving the pointer.
1744+
/// * Performing unsizing coercions on the pointer.
1745+
/// * Performing dynamic dispatch with the pointer.
1746+
/// * Calling `deref` or `deref_mut` on the pointer.
1747+
///
1748+
/// The concrete type of a trait object is the type that the vtable corresponds
1749+
/// to. The concrete type of a slice is an array of the same element type and
1750+
/// the length specified in the metadata. The concrete type of a sized type
1751+
/// is the type itself.
1752+
pub unsafe trait PinCoerceUnsized {}
1753+
1754+
#[stable(feature = "pin", since = "1.33.0")]
1755+
unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a T {}
1756+
1757+
#[stable(feature = "pin", since = "1.33.0")]
1758+
unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a mut T {}
1759+
1760+
#[stable(feature = "pin", since = "1.33.0")]
1761+
unsafe impl<T: PinCoerceUnsized> PinCoerceUnsized for Pin<T> {}
1762+
1763+
#[stable(feature = "pin", since = "1.33.0")]
1764+
unsafe impl<T: ?Sized> PinCoerceUnsized for *const T {}
17191765

17201766
#[stable(feature = "pin", since = "1.33.0")]
1721-
impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr> where Ptr: DispatchFromDyn<U> {}
1767+
unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
17221768

17231769
/// Constructs a <code>[Pin]<[&mut] T></code>, by pinning a `value: T` locally.
17241770
///

library/core/src/ptr/non_null.rs

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::marker::Unsize;
33
use crate::mem::{MaybeUninit, SizedTypeProperties};
44
use crate::num::NonZero;
55
use crate::ops::{CoerceUnsized, DispatchFromDyn};
6+
use crate::pin::PinCoerceUnsized;
67
use crate::ptr::Unique;
78
use crate::slice::{self, SliceIndex};
89
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
17241725
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
17251726
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NonNull<U>> for NonNull<T> where T: Unsize<U> {}
17261727

1728+
#[stable(feature = "pin", since = "1.33.0")]
1729+
unsafe impl<T: ?Sized> PinCoerceUnsized for NonNull<T> {}
1730+
17271731
#[stable(feature = "nonnull", since = "1.25.0")]
17281732
impl<T: ?Sized> fmt::Debug for NonNull<T> {
17291733
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

library/core/src/ptr/unique.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::fmt;
22
use crate::marker::{PhantomData, Unsize};
33
use crate::ops::{CoerceUnsized, DispatchFromDyn};
4+
use crate::pin::PinCoerceUnsized;
45
use crate::ptr::NonNull;
56

67
/// 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
166167
#[unstable(feature = "ptr_internals", issue = "none")]
167168
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Unique<U>> for Unique<T> where T: Unsize<U> {}
168169

170+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
171+
unsafe impl<T: ?Sized> PinCoerceUnsized for Unique<T> {}
172+
169173
#[unstable(feature = "ptr_internals", issue = "none")]
170174
impl<T: ?Sized> fmt::Debug for Unique<T> {
171175
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

library/core/tests/pin.rs

+46
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,49 @@ fn pin_const() {
2929

3030
pin_mut_const();
3131
}
32+
33+
#[allow(unused)]
34+
mod pin_coerce_unsized {
35+
use core::cell::{Cell, RefCell, UnsafeCell};
36+
use core::pin::Pin;
37+
use core::ptr::NonNull;
38+
39+
pub trait MyTrait {}
40+
impl MyTrait for String {}
41+
42+
// These Pins should continue to compile.
43+
// Do note that these instances of Pin types cannot be used
44+
// meaningfully because all methods require a Deref/DerefMut
45+
// bounds on the pointer type and Cell, RefCell and UnsafeCell
46+
// do not implement Deref/DerefMut.
47+
48+
pub fn cell(arg: Pin<Cell<Box<String>>>) -> Pin<Cell<Box<dyn MyTrait>>> {
49+
arg
50+
}
51+
pub fn ref_cell(arg: Pin<RefCell<Box<String>>>) -> Pin<RefCell<Box<dyn MyTrait>>> {
52+
arg
53+
}
54+
pub fn unsafe_cell(arg: Pin<UnsafeCell<Box<String>>>) -> Pin<UnsafeCell<Box<dyn MyTrait>>> {
55+
arg
56+
}
57+
58+
// These sensible Pin coercions are possible.
59+
pub fn pin_mut_ref(arg: Pin<&mut String>) -> Pin<&mut dyn MyTrait> {
60+
arg
61+
}
62+
pub fn pin_ref(arg: Pin<&String>) -> Pin<&dyn MyTrait> {
63+
arg
64+
}
65+
pub fn pin_ptr(arg: Pin<*const String>) -> Pin<*const dyn MyTrait> {
66+
arg
67+
}
68+
pub fn pin_ptr_mut(arg: Pin<*mut String>) -> Pin<*mut dyn MyTrait> {
69+
arg
70+
}
71+
pub fn pin_non_null(arg: Pin<NonNull<String>>) -> Pin<NonNull<dyn MyTrait>> {
72+
arg
73+
}
74+
pub fn nesting_pins(arg: Pin<Pin<&String>>) -> Pin<Pin<&dyn MyTrait>> {
75+
arg
76+
}
77+
}

library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs

+3
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,9 @@ where
751751
#[unstable(feature = "sgx_platform", issue = "56975")]
752752
impl<T: CoerceUnsized<U>, U> CoerceUnsized<UserRef<U>> for UserRef<T> {}
753753

754+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
755+
unsafe impl<T: ?Sized> PinCoerceUnsized for UserRef<T> {}
756+
754757
#[unstable(feature = "sgx_platform", issue = "56975")]
755758
impl<T, I> Index<I> for UserRef<[T]>
756759
where

0 commit comments

Comments
 (0)