Skip to content

Commit ea678b7

Browse files
PinCoerceUnsized trait into core
1 parent d3dd34a commit ea678b7

File tree

12 files changed

+170
-4
lines changed

12 files changed

+170
-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
@@ -203,7 +203,7 @@ use core::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce};
203203
use core::ops::{
204204
CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver,
205205
};
206-
use core::pin::Pin;
206+
use core::pin::{Pin, PinCoerceUnsized};
207207
use core::ptr::{self, addr_of_mut, NonNull, Unique};
208208
use core::slice;
209209
use core::task::{Context, Poll};
@@ -2646,3 +2646,6 @@ impl<T: core::error::Error> core::error::Error for Box<T> {
26462646
core::error::Error::provide(&**self, request);
26472647
}
26482648
}
2649+
2650+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2651+
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

+7
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Rece
264264
use core::panic::{RefUnwindSafe, UnwindSafe};
265265
#[cfg(not(no_global_oom_handling))]
266266
use core::pin::Pin;
267+
use core::pin::PinCoerceUnsized;
267268
use core::ptr::{self, drop_in_place, NonNull};
268269
#[cfg(not(no_global_oom_handling))]
269270
use core::slice::from_raw_parts_mut;
@@ -2181,6 +2182,9 @@ impl<T: ?Sized, A: Allocator> Deref for Rc<T, A> {
21812182
}
21822183
}
21832184

2185+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2186+
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Rc<T, A> {}
2187+
21842188
#[unstable(feature = "deref_pure_trait", issue = "87121")]
21852189
unsafe impl<T: ?Sized, A: Allocator> DerefPure for Rc<T, A> {}
21862190

@@ -3696,6 +3700,9 @@ impl<T: ?Sized, A: Allocator> Deref for UniqueRc<T, A> {
36963700
}
36973701
}
36983702

3703+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
3704+
unsafe impl<T: ?Sized> PinCoerceUnsized for UniqueRc<T> {}
3705+
36993706
#[unstable(feature = "unique_rc_arc", issue = "112566")]
37003707
impl<T: ?Sized, A: Allocator> DerefMut for UniqueRc<T, A> {
37013708
fn deref_mut(&mut self) -> &mut T {

library/alloc/src/sync.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use core::marker::{PhantomData, Unsize};
2323
use core::mem::{self, align_of_val_raw};
2424
use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver};
2525
use core::panic::{RefUnwindSafe, UnwindSafe};
26-
use core::pin::Pin;
26+
use core::pin::{Pin, PinCoerceUnsized};
2727
use core::ptr::{self, NonNull};
2828
#[cfg(not(no_global_oom_handling))]
2929
use core::slice::from_raw_parts_mut;
@@ -2147,6 +2147,9 @@ impl<T: ?Sized, A: Allocator> Deref for Arc<T, A> {
21472147
}
21482148
}
21492149

2150+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2151+
unsafe impl<T: ?Sized, A: Allocator> PinCoerceUnsized for Arc<T, A> {}
2152+
21502153
#[unstable(feature = "deref_pure_trait", issue = "87121")]
21512154
unsafe impl<T: ?Sized, A: Allocator> DerefPure for Arc<T, A> {}
21522155

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

+10
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;
@@ -2394,3 +2395,12 @@ fn assert_coerce_unsized(
23942395
let _: Cell<&dyn Send> = c;
23952396
let _: RefCell<&dyn Send> = d;
23962397
}
2398+
2399+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2400+
unsafe impl<T: ?Sized> PinCoerceUnsized for UnsafeCell<T> {}
2401+
2402+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2403+
unsafe impl<T: ?Sized> PinCoerceUnsized for Cell<T> {}
2404+
2405+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
2406+
unsafe impl<T: ?Sized> PinCoerceUnsized for RefCell<T> {}

library/core/src/pin.rs

+42-2
Original file line numberDiff line numberDiff line change
@@ -1717,10 +1717,50 @@ impl<Ptr: fmt::Pointer> fmt::Pointer for Pin<Ptr> {
17171717
// for other reasons, though, so we just need to take care not to allow such
17181718
// impls to land in std.
17191719
#[stable(feature = "pin", since = "1.33.0")]
1720-
impl<Ptr, U> CoerceUnsized<Pin<U>> for Pin<Ptr> where Ptr: CoerceUnsized<U> {}
1720+
impl<Ptr, U> CoerceUnsized<Pin<U>> for Pin<Ptr>
1721+
where
1722+
Ptr: CoerceUnsized<U> + PinCoerceUnsized,
1723+
U: PinCoerceUnsized,
1724+
{
1725+
}
1726+
1727+
#[stable(feature = "pin", since = "1.33.0")]
1728+
impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr>
1729+
where
1730+
Ptr: DispatchFromDyn<U> + PinCoerceUnsized,
1731+
U: PinCoerceUnsized,
1732+
{
1733+
}
1734+
1735+
#[unstable(feature = "pin_coerce_unsized_trait", issue = "123430")]
1736+
/// # Safety
1737+
///
1738+
/// Implementing this unsafe traits requires the guarantee that any two calls
1739+
/// to `Deref::deref` must return the same value at the same address, **even after moves
1740+
/// or unsize-coercions of `self`**, with exceptions of mutations to `self`.
1741+
///
1742+
/// Here, "same value" means that if `deref` returns a trait object, then the actual
1743+
/// concrete type behind that trait object must not change.
1744+
/// Additionally, when you unsize- coerce from `Self` to `Unsized`,
1745+
/// then if you call `deref` on `Unsized` which returns a trait object reference,
1746+
/// the underlying type of that trait object must be `<Self as Deref>::Target`.
1747+
///
1748+
/// Analogous requirements apply to other unsized types. E.g., if `deref` returns
1749+
/// `[T]`, then the length must not change. In other words, the underlying type
1750+
/// must not change from `[T; N]` to `[T; M]` with an `N` different from `M`.
1751+
///
1752+
/// If this type alos implements `DerefMut`, then the same guarantee must be upheld by
1753+
/// calls to `deref_mut`.
1754+
pub unsafe trait PinCoerceUnsized {}
1755+
1756+
#[stable(feature = "pin", since = "1.33.0")]
1757+
unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a T {}
1758+
1759+
#[stable(feature = "pin", since = "1.33.0")]
1760+
unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a mut T {}
17211761

17221762
#[stable(feature = "pin", since = "1.33.0")]
1723-
impl<Ptr, U> DispatchFromDyn<Pin<U>> for Pin<Ptr> where Ptr: DispatchFromDyn<U> {}
1763+
unsafe impl<T: PinCoerceUnsized> PinCoerceUnsized for Pin<T> {}
17241764

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

library/core/tests/pin.rs

+32
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,35 @@ 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+
38+
// These Pins should continue to compile.
39+
// Do note that these instances of Pin types cannot be used
40+
// meaningfully because all methods require a Deref/DerefMut
41+
// bounds on the pointer type and Cell, RefCell and UnsafeCell
42+
// do not implement Deref/DerefMut.
43+
pub trait MyTrait {}
44+
impl MyTrait for String {}
45+
46+
pub fn cell(arg: Pin<Cell<Box<String>>>) -> Pin<Cell<Box<dyn MyTrait>>> {
47+
arg
48+
}
49+
pub fn ref_cell(arg: Pin<RefCell<Box<String>>>) -> Pin<RefCell<Box<dyn MyTrait>>> {
50+
arg
51+
}
52+
pub fn unsafe_cell(arg: Pin<UnsafeCell<Box<String>>>) -> Pin<UnsafeCell<Box<dyn MyTrait>>> {
53+
arg
54+
}
55+
56+
// These sensible Pin coercions are possible.
57+
pub fn pin_mut_ref(arg: Pin<&mut String>) -> Pin<&mut dyn MyTrait> {
58+
arg
59+
}
60+
pub fn pin_ref(arg: Pin<&String>) -> Pin<&dyn MyTrait> {
61+
arg
62+
}
63+
}

0 commit comments

Comments
 (0)