Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 9d7facc

Browse files
authoredNov 11, 2024
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, rust-lang/rfcs#3519 #44874 r? `@wesleywiser`
2 parents 3ab4477 + ecfcd08 commit 9d7facc

File tree

4 files changed

+93
-2
lines changed

4 files changed

+93
-2
lines changed
 

‎compiler/rustc_hir/src/lang_items.rs

+2
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ language_item_table! {
241241
DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
242242
DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0);
243243
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
244+
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
245+
ReceiverTarget, sym::receiver_target, receiver_target, Target::AssocTy, GenericRequirement::None;
244246
LegacyReceiver, sym::legacy_receiver, legacy_receiver_trait, Target::Trait, GenericRequirement::None;
245247

246248
Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);

‎compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1568,6 +1568,8 @@ symbols! {
15681568
readonly,
15691569
realloc,
15701570
reason,
1571+
receiver,
1572+
receiver_target,
15711573
recursion_limit,
15721574
reexport_test_harness_main,
15731575
ref_pat_eat_one_layer_2024,

‎library/core/src/ops/deref.rs

+86-2
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,98 @@ unsafe impl<T: ?Sized> DerefPure for &T {}
294294
#[unstable(feature = "deref_pure_trait", issue = "87121")]
295295
unsafe impl<T: ?Sized> DerefPure for &mut T {}
296296

297+
/// Indicates that a struct can be used as a method receiver.
298+
/// That is, a type can use this type as a type of `self`, like this:
299+
/// ```compile_fail
300+
/// # // This is currently compile_fail because the compiler-side parts
301+
/// # // of arbitrary_self_types are not implemented
302+
/// use std::ops::Receiver;
303+
///
304+
/// struct SmartPointer<T>(T);
305+
///
306+
/// impl<T> Receiver for SmartPointer<T> {
307+
/// type Target = T;
308+
/// }
309+
///
310+
/// struct MyContainedType;
311+
///
312+
/// impl MyContainedType {
313+
/// fn method(self: SmartPointer<Self>) {
314+
/// // ...
315+
/// }
316+
/// }
317+
///
318+
/// fn main() {
319+
/// let ptr = SmartPointer(MyContainedType);
320+
/// ptr.method();
321+
/// }
322+
/// ```
323+
/// This trait is blanket implemented for any type which implements
324+
/// [`Deref`], which includes stdlib pointer types like `Box<T>`,`Rc<T>`, `&T`,
325+
/// and `Pin<P>`. For that reason, it's relatively rare to need to
326+
/// implement this directly. You'll typically do this only if you need
327+
/// to implement a smart pointer type which can't implement [`Deref`]; perhaps
328+
/// because you're interfacing with another programming language and can't
329+
/// guarantee that references comply with Rust's aliasing rules.
330+
///
331+
/// When looking for method candidates, Rust will explore a chain of possible
332+
/// `Receiver`s, so for example each of the following methods work:
333+
/// ```
334+
/// use std::boxed::Box;
335+
/// use std::rc::Rc;
336+
///
337+
/// // Both `Box` and `Rc` (indirectly) implement Receiver
338+
///
339+
/// struct MyContainedType;
340+
///
341+
/// fn main() {
342+
/// let t = Rc::new(Box::new(MyContainedType));
343+
/// t.method_a();
344+
/// t.method_b();
345+
/// t.method_c();
346+
/// }
347+
///
348+
/// impl MyContainedType {
349+
/// fn method_a(&self) {
350+
///
351+
/// }
352+
/// fn method_b(self: &Box<Self>) {
353+
///
354+
/// }
355+
/// fn method_c(self: &Rc<Box<Self>>) {
356+
///
357+
/// }
358+
/// }
359+
/// ```
360+
#[lang = "receiver"]
361+
#[cfg(not(bootstrap))]
362+
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
363+
pub trait Receiver {
364+
/// The target type on which the method may be called.
365+
#[cfg(not(bootstrap))]
366+
#[rustc_diagnostic_item = "receiver_target"]
367+
#[lang = "receiver_target"]
368+
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
369+
type Target: ?Sized;
370+
}
371+
372+
#[cfg(not(bootstrap))]
373+
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
374+
impl<P: ?Sized, T: ?Sized> Receiver for P
375+
where
376+
P: Deref<Target = T>,
377+
{
378+
type Target = T;
379+
}
380+
297381
/// Indicates that a struct can be used as a method receiver, without the
298382
/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
299383
/// `Rc<T>`, `&T`, and `Pin<P>`.
300384
///
301385
/// This trait will shortly be removed and replaced with a more generic
302386
/// facility based around the current "arbitrary self types" unstable feature.
303-
/// That new facility will use a replacement trait called `Receiver` which is
304-
/// why this is now named `LegacyReceiver`.
387+
/// That new facility will use the replacement trait above called `Receiver`
388+
/// which is why this is now named `LegacyReceiver`.
305389
#[cfg_attr(bootstrap, lang = "receiver")]
306390
#[cfg_attr(not(bootstrap), lang = "legacy_receiver")]
307391
#[unstable(feature = "legacy_receiver_trait", issue = "none")]

‎library/core/src/ops/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ pub use self::coroutine::{Coroutine, CoroutineState};
170170
pub use self::deref::DerefPure;
171171
#[unstable(feature = "legacy_receiver_trait", issue = "none")]
172172
pub use self::deref::LegacyReceiver;
173+
#[unstable(feature = "arbitrary_self_types", issue = "44874")]
174+
#[cfg(not(bootstrap))]
175+
pub use self::deref::Receiver;
173176
#[stable(feature = "rust1", since = "1.0.0")]
174177
pub use self::deref::{Deref, DerefMut};
175178
#[stable(feature = "rust1", since = "1.0.0")]

0 commit comments

Comments
 (0)
Failed to load comments.