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..e8e6e089eae95 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -309,3 +309,25 @@ impl Receiver for &T {} #[unstable(feature = "receiver_trait", issue = "none")] impl Receiver for &mut T {} + +#[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 {}