diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index c4be67cdd887f..e33ae44cf56fd 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -220,6 +220,7 @@ language_item_table! { DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0); DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None; Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None; + StableDeref, sym::stable_deref, stable_deref_trait, Target::Trait, GenericRequirement::Exact(0); Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1); FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d41059e8c24a4..bc9c50c10f359 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, @@ -1767,6 +1768,7 @@ symbols! { sse, sse4a_target_feature, stable, + stable_deref, staged_api, start, state, diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 9849410d484ca..4ec8a6b50e238 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -309,3 +309,26 @@ impl Receiver for &T {} #[unstable(feature = "receiver_trait", issue = "none")] impl Receiver for &mut T {} + +#[cfg(not(bootstrap))] +#[lang = "stable_deref"] +#[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/pin.rs b/library/core/src/pin.rs index d8fc3b7177f38..cf209be10e1eb 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -923,6 +923,8 @@ use crate::cmp; use crate::fmt; use crate::hash::{Hash, Hasher}; +#[cfg(not(bootstrap))] +use crate::ops::StableDeref; use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver}; #[allow(unused_imports)] @@ -1716,12 +1718,32 @@ impl fmt::Pointer for Pin { // `Deref` is unsound. Any such impl would probably be unsound // for other reasons, though, so we just need to take care not to allow such // impls to land in std. +#[cfg(bootstrap)] #[stable(feature = "pin", since = "1.33.0")] impl CoerceUnsized> for Pin where Ptr: CoerceUnsized {} +#[cfg(bootstrap)] #[stable(feature = "pin", since = "1.33.0")] impl DispatchFromDyn> for Pin where Ptr: DispatchFromDyn {} +#[cfg(not(bootstrap))] +#[stable(feature = "pin", since = "1.33.0")] +impl CoerceUnsized> for Pin +where + Ptr: CoerceUnsized + StableDeref, + U: StableDeref, +{ +} + +#[cfg(not(bootstrap))] +#[stable(feature = "pin", since = "1.33.0")] +impl DispatchFromDyn> for Pin +where + Ptr: DispatchFromDyn + StableDeref, + U: StableDeref, +{ +} + /// Constructs a [Pin]<[&mut] T>, by pinning a `value: T` locally. /// /// Unlike [`Box::pin`], this does not create a new heap allocation. As explained