Rollup merge of #125048 - dingxiangfei2009:stable-deref, r=amanieu
PinCoerceUnsized trait into core cc ``@Darksonn`` ``@wedsonaf`` ``@ojeda`` This is a PR to introduce a `PinCoerceUnsized` trait in order to make trait impls generated by the proc-macro `#[derive(SmartPointer)]`, proposed by [RFC](e17e19ac7a/text/3621-derive-smart-pointer.md (pincoerceunsized-1)
), sound. There you may find explanation, justification and discussion about the alternatives. Note that we do not seek stabilization of this `PinCoerceUnsized` trait in the near future. The stabilisation of this trait does not block the eventual stabilization process of the `#[derive(SmartPointer)]` macro. Ideally, use of `DerefPure` is more preferrable except this will actually constitute a breaking change. `PinCoerceUnsized` emerges as a solution to the said soundness hole while avoiding the breaking change. More details on the `DerefPure` option have been described in this [section](e17e19ac7a/text/3621-derive-smart-pointer.md (derefpure)
) of the RFC linked above. Earlier discussion can be found in this [Zulip stream](https://rust-lang.zulipchat.com/#narrow/stream/136281-t-opsem/topic/Pin.20and.20soundness.20of.20unsizing.20coercions) and [rust-for-linux thread](https://rust-lang.zulipchat.com/#narrow/stream/425075-rust-for-linux/topic/.23.5Bderive.28SmartPointer.29.5D.20and.20pin.20unsoundness.20rfc.233621). try-job: dist-various-2
This commit is contained in:
commit
16b251be10
@ -276,6 +276,7 @@
|
||||
Path,
|
||||
PathBuf,
|
||||
Pending,
|
||||
PinCoerceUnsized,
|
||||
Pointer,
|
||||
Poll,
|
||||
ProcMacro,
|
||||
|
@ -200,7 +200,7 @@
|
||||
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 @@ fn provide<'b>(&'b self, request: &mut core::error::Request<'b>) {
|
||||
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> {}
|
||||
|
@ -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)]
|
||||
|
@ -256,6 +256,7 @@
|
||||
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 @@ fn deref(&self) -> &T {
|
||||
}
|
||||
}
|
||||
|
||||
#[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> {}
|
||||
|
||||
@ -3691,6 +3698,9 @@ fn deref(&self) -> &T {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
|
@ -20,7 +20,7 @@
|
||||
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 @@ fn deref(&self) -> &T {
|
||||
}
|
||||
}
|
||||
|
||||
#[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> {}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -179,3 +179,40 @@ fn by_ref(&self) -> &Self
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -205,3 +205,20 @@ fn hmm<'a>(val: &'a mut Weak<&'a str>) -> Weak<&'a str> {
|
||||
// `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
|
||||
}
|
||||
}
|
||||
|
@ -255,6 +255,7 @@
|
||||
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> {}
|
||||
|
@ -1715,10 +1715,56 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// 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> {}
|
||||
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")]
|
||||
unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {}
|
||||
|
||||
/// Constructs a <code>[Pin]<[&mut] T></code>, by pinning a `value: T` locally.
|
||||
///
|
||||
|
@ -3,6 +3,7 @@
|
||||
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 {
|
||||
|
@ -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 {
|
||||
|
@ -29,3 +29,49 @@ const fn pin_mut_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
|
||||
}
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -8,6 +8,7 @@
|
||||
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 @@ fn drop(&mut self) {
|
||||
#[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
|
||||
|
Loading…
Reference in New Issue
Block a user