diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d41059e8c24a4..be018cc51adc9 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -302,6 +302,7 @@ symbols! { SliceIter, Some, SpanCtxt, + StableDeref, String, StructuralPartialEq, SubdiagMessage, diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index e5d62447eb20e..6acfde8360d39 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -159,6 +159,8 @@ use core::iter::FusedIterator; use core::marker::Tuple; use core::marker::Unsize; use core::mem::{self, SizedTypeProperties}; +#[unstable(feature = "stable_deref_trait", issue = "123430")] +use core::ops::StableDeref; use core::ops::{AsyncFn, AsyncFnMut, AsyncFnOnce}; use core::ops::{ CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver, @@ -2505,3 +2507,6 @@ impl core::error::Error for Box { core::error::Error::provide(&**self, request); } } + +#[unstable(feature = "stable_deref_trait", issue = "123430")] +unsafe impl StableDeref for Box {} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 91b83cfe011f2..6ede610b1c930 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -149,6 +149,7 @@ #![feature(slice_index_methods)] #![feature(slice_ptr_get)] #![feature(slice_range)] +#![feature(stable_deref_trait)] #![feature(std_internals)] #![feature(str_internals)] #![feature(strict_provenance)] diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 9849410d484ca..d4eb4d4c062be 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -309,3 +309,24 @@ impl Receiver for &T {} #[unstable(feature = "receiver_trait", issue = "none")] impl Receiver for &mut T {} + +#[unstable(feature = "stable_deref_trait", issue = "123430")] +/// # Safety +/// +/// Any two calls to `deref` must return the same value at the same address unless +/// `self` has been modified in the meantime. Moves and unsizing coercions of `self` +/// are not considered modifications. +/// +/// Here, "same value" means that if `deref` returns a trait object, then the actual +/// type behind that trait object must not change. Additionally, when you unsize +/// coerce from `Self` to `Unsized`, then if you call `deref` on `Unsized` and get a +/// trait object, then the underlying type of that trait object must be `::Target`. +/// +/// Analogous requirements apply to other unsized types. E.g., if `deref` returns +/// `[T]`, then the length must not change. In other words, the underlying type +/// must not change from `[T; N]` to `[T; M]`. +/// +/// If this type implements `DerefMut`, then the same restrictions apply to calls +/// to `deref_mut`. +pub unsafe trait StableDeref: Deref {} diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 7bcfaadbe372b..a3e5412b2310f 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -171,6 +171,9 @@ pub use self::deref::DerefPure; #[unstable(feature = "receiver_trait", issue = "none")] pub use self::deref::Receiver; +#[unstable(feature = "stable_deref_trait", issue = "123430")] +pub use self::deref::StableDeref; + #[stable(feature = "rust1", since = "1.0.0")] pub use self::drop::Drop; diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index d8fc3b7177f38..af0fa80326694 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -923,7 +923,9 @@ use crate::cmp; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver}; +use crate::ops::{ + CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver, StableDeref, +}; #[allow(unused_imports)] use crate::{ @@ -1717,10 +1719,29 @@ 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 + StableDeref, + U: StableDeref, +{ +} + +#[stable(feature = "pin", since = "1.33.0")] +impl DispatchFromDyn> for Pin +where + Ptr: DispatchFromDyn + StableDeref, + U: StableDeref, +{ +} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl<'a, T: ?Sized> StableDeref for &'a T {} + +#[stable(feature = "pin", since = "1.33.0")] +unsafe impl<'a, T: ?Sized> StableDeref for &'a mut T {} #[stable(feature = "pin", since = "1.33.0")] -impl DispatchFromDyn> for Pin where Ptr: DispatchFromDyn {} +unsafe impl StableDeref for Pin {} /// Constructs a [Pin]<[&mut] T>, by pinning a `value: T` locally. ///