about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-11-11 21:58:29 +0100
committerGitHub <noreply@github.com>2024-11-11 21:58:29 +0100
commit9d7faccffc8b5d7a10badb3ed798d96cb6f1ed07 (patch)
tree1d67503e846e9170c769069b9f19903fe7038099
parent3ab4477ba77ce0745424c0b37754345b83fbf6fd (diff)
parentecfcd0879cf9e54992328403655ec4aaeee1a6a9 (diff)
downloadrust-9d7faccffc8b5d7a10badb3ed798d96cb6f1ed07.tar.gz
rust-9d7faccffc8b5d7a10badb3ed798d96cb6f1ed07.zip
Rollup merge of #132144 - adetaylor:receiver-trait-itself, r=wesleywiser
Arbitrary self types v2: (unused) Receiver trait

This commit contains a new `Receiver` trait, which is the basis for the Arbitrary Self Types v2 RFC. This allows smart pointers to be method receivers even if they're not Deref.

This is currently unused by the compiler - a subsequent PR will start to use this for method resolution if the `arbitrary_self_types` feature gate is enabled. This is being landed first simply to make review simpler: if people feel this should all be in an atomic PR let me know.

This is a part of the arbitrary self types v2 project, https://github.com/rust-lang/rfcs/pull/3519
https://github.com/rust-lang/rust/issues/44874

r? `@wesleywiser`
-rw-r--r--compiler/rustc_hir/src/lang_items.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--library/core/src/ops/deref.rs88
-rw-r--r--library/core/src/ops/mod.rs3
4 files changed, 93 insertions, 2 deletions
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index c952d5f6d77..15cb331d07a 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -241,6 +241,8 @@ language_item_table! {
     DerefMut,                sym::deref_mut,           deref_mut_trait,            Target::Trait,          GenericRequirement::Exact(0);
     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;
+    ReceiverTarget,          sym::receiver_target,     receiver_target,            Target::AssocTy,        GenericRequirement::None;
     LegacyReceiver,          sym::legacy_receiver,     legacy_receiver_trait,      Target::Trait,          GenericRequirement::None;
 
     Fn,                      kw::Fn,                   fn_trait,                   Target::Trait,          GenericRequirement::Exact(1);
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f89fd0f7f2a..42c6221dc57 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1568,6 +1568,8 @@ symbols! {
         readonly,
         realloc,
         reason,
+        receiver,
+        receiver_target,
         recursion_limit,
         reexport_test_harness_main,
         ref_pat_eat_one_layer_2024,
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index 1ef9990c00a..45688727c9b 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -294,14 +294,98 @@ unsafe impl<T: ?Sized> DerefPure for &T {}
 #[unstable(feature = "deref_pure_trait", issue = "87121")]
 unsafe impl<T: ?Sized> DerefPure for &mut T {}
 
+/// Indicates that a struct can be used as a method receiver.
+/// That is, a type can use this type as a type of `self`, like this:
+/// ```compile_fail
+/// # // This is currently compile_fail because the compiler-side parts
+/// # // of arbitrary_self_types are not implemented
+/// use std::ops::Receiver;
+///
+/// struct SmartPointer<T>(T);
+///
+/// impl<T> Receiver for SmartPointer<T> {
+///    type Target = T;
+/// }
+///
+/// struct MyContainedType;
+///
+/// impl MyContainedType {
+///   fn method(self: SmartPointer<Self>) {
+///     // ...
+///   }
+/// }
+///
+/// fn main() {
+///   let ptr = SmartPointer(MyContainedType);
+///   ptr.method();
+/// }
+/// ```
+/// This trait is blanket implemented for any type which implements
+/// [`Deref`], which includes stdlib pointer types like `Box<T>`,`Rc<T>`, `&T`,
+/// and `Pin<P>`. For that reason, it's relatively rare to need to
+/// implement this directly. You'll typically do this only if you need
+/// to implement a smart pointer type which can't implement [`Deref`]; perhaps
+/// because you're interfacing with another programming language and can't
+/// guarantee that references comply with Rust's aliasing rules.
+///
+/// When looking for method candidates, Rust will explore a chain of possible
+/// `Receiver`s, so for example each of the following methods work:
+/// ```
+/// use std::boxed::Box;
+/// use std::rc::Rc;
+///
+/// // Both `Box` and `Rc` (indirectly) implement Receiver
+///
+/// struct MyContainedType;
+///
+/// fn main() {
+///   let t = Rc::new(Box::new(MyContainedType));
+///   t.method_a();
+///   t.method_b();
+///   t.method_c();
+/// }
+///
+/// impl MyContainedType {
+///   fn method_a(&self) {
+///
+///   }
+///   fn method_b(self: &Box<Self>) {
+///
+///   }
+///   fn method_c(self: &Rc<Box<Self>>) {
+///
+///   }
+/// }
+/// ```
+#[lang = "receiver"]
+#[cfg(not(bootstrap))]
+#[unstable(feature = "arbitrary_self_types", issue = "44874")]
+pub trait Receiver {
+    /// The target type on which the method may be called.
+    #[cfg(not(bootstrap))]
+    #[rustc_diagnostic_item = "receiver_target"]
+    #[lang = "receiver_target"]
+    #[unstable(feature = "arbitrary_self_types", issue = "44874")]
+    type Target: ?Sized;
+}
+
+#[cfg(not(bootstrap))]
+#[unstable(feature = "arbitrary_self_types", issue = "44874")]
+impl<P: ?Sized, T: ?Sized> Receiver for P
+where
+    P: Deref<Target = T>,
+{
+    type Target = T;
+}
+
 /// Indicates that a struct can be used as a method receiver, without the
 /// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
 /// `Rc<T>`, `&T`, and `Pin<P>`.
 ///
 /// This trait will shortly be removed and replaced with a more generic
 /// facility based around the current "arbitrary self types" unstable feature.
-/// That new facility will use a replacement trait called `Receiver` which is
-/// why this is now named `LegacyReceiver`.
+/// That new facility will use the replacement trait above called `Receiver`
+/// which is why this is now named `LegacyReceiver`.
 #[cfg_attr(bootstrap, lang = "receiver")]
 #[cfg_attr(not(bootstrap), lang = "legacy_receiver")]
 #[unstable(feature = "legacy_receiver_trait", issue = "none")]
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index c9f47e5daad..cea1f84f3fd 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -170,6 +170,9 @@ pub use self::coroutine::{Coroutine, CoroutineState};
 pub use self::deref::DerefPure;
 #[unstable(feature = "legacy_receiver_trait", issue = "none")]
 pub use self::deref::LegacyReceiver;
+#[unstable(feature = "arbitrary_self_types", issue = "44874")]
+#[cfg(not(bootstrap))]
+pub use self::deref::Receiver;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::deref::{Deref, DerefMut};
 #[stable(feature = "rust1", since = "1.0.0")]