From 27ab965792e337d280eb948fb71ba18dcfbb4e23 Mon Sep 17 00:00:00 2001 From: Adrian Taylor Date: Thu, 19 Dec 2024 13:01:18 +0000 Subject: [PATCH] Arbitrary self types v2: update reference. --- src/expressions/method-call-expr.md | 22 +++++++++++++++++++++- src/items/associated-items.md | 13 +++++-------- src/special-types-and-traits.md | 11 ++++++++++- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/expressions/method-call-expr.md b/src/expressions/method-call-expr.md index 9535cd207..19a25bd91 100644 --- a/src/expressions/method-call-expr.md +++ b/src/expressions/method-call-expr.md @@ -23,7 +23,18 @@ Then, for each candidate `T`, add `&T` and `&mut T` to the list immediately afte For instance, if the receiver has type `Box<[i32;2]>`, then the candidate types will be `Box<[i32;2]>`, `&Box<[i32;2]>`, `&mut Box<[i32;2]>`, `[i32; 2]` (by dereferencing), `&[i32; 2]`, `&mut [i32; 2]`, `[i32]` (by unsized coercion), `&[i32]`, and finally `&mut [i32]`. -Then, for each candidate type `T`, search for a [visible] method with a receiver of that type in the following places: +A second - possible more expansive - list is then made of types where we might +find [visible] methods with a receiver of that type, called the list of +contributing types. To make this list, follow the exact same process, +but this time use the `Receiver` trait +instead of the `Deref` trait for any non-built-in derefences. + +There is a blanket implementation of `Receiver` for all `T: Deref`, so in many +cases the lists are identical, but there are rare smart pointers which +may implement `Receiver` without implementing `Deref`, so this second list of +types may be longer than the list of candidate types. + +Then, for each contributing type `T`, search for a [visible] method with a receiver of any candidate type in the following places: 1. `T`'s inherent methods (methods implemented directly on `T`). 1. Any of the methods provided by a [visible] trait implemented by `T`. @@ -66,6 +77,15 @@ Once a method is looked up, if it can't be called for one (or more) of those rea If a step is reached where there is more than one possible method, such as where generic methods or traits are considered the same, then it is a compiler error. These cases require a [disambiguating function call syntax] for method and function invocation. +As well as emitting methods for multiple candidates within a given step, +an additional search may be performed to look for specific cases where an outer +(smart pointer) type may have a method that shadows or overrides a method +on its referent. This process is performed if we are about to return a method +identified by a by-value step; a search is then performed for a matching by-reference +methods deeper along the chain of contributing types with an identical `self` type. +This extra search is also performed if we are about to return a method from +a `&T` pick; error are emitted if a `&mut T` method would be shadowed. + > **Edition differences**: Before the 2021 edition, during the search for visible methods, if the candidate receiver type is an [array type], methods provided by the standard library [`IntoIterator`] trait are ignored. > > The edition used for this purpose is determined by the token representing the method name. diff --git a/src/items/associated-items.md b/src/items/associated-items.md index 3df2e0eee..039670ba9 100644 --- a/src/items/associated-items.md +++ b/src/items/associated-items.md @@ -113,15 +113,11 @@ well as the usual function call notation. r[items.associated.fn.method.self-ty] If the type of the `self` parameter is specified, it is limited to types resolving -to one generated by the following grammar (where `'lt` denotes some arbitrary -lifetime): +to a type implementing the [`Receiver`] trait with a `Target` associated type +matching the implementing type. Typically, this means the type itself, a +reference to it, or a smart pointer referring to it (such as [`Box`] +or [`Arc`]). -```text -P = &'lt S | &'lt mut S | Box | Rc | Arc | Pin

-S = Self | P -``` - -The `Self` terminal in this grammar denotes a type resolving to the implementing type. This can also include the contextual type alias `Self`, other type aliases, or associated type projections resolving to the implementing type. @@ -571,6 +567,7 @@ fn main() { [`Pin

`]: ../special-types-and-traits.md#pinp [`Rc`]: ../special-types-and-traits.md#rct [`Sized`]: ../special-types-and-traits.md#sized +[`Receiver`]: ../special-types-and-traits.md#receiver [traits]: traits.md [type aliases]: type-aliases.md [inherent implementations]: implementations.md#inherent-implementations diff --git a/src/special-types-and-traits.md b/src/special-types-and-traits.md index f7e98323d..637399f43 100644 --- a/src/special-types-and-traits.md +++ b/src/special-types-and-traits.md @@ -49,7 +49,15 @@ The traits in [`std::ops`] and [`std::cmp`] are used to overload [operators], ## `Deref` and `DerefMut` As well as overloading the unary `*` operator, [`Deref`] and [`DerefMut`] are -also used in [method resolution] and [deref coercions]. +also used in [deref coercions]; see also [`Receiver`] below. + +## `Receiver` + +[`Receiver`] is used in [method resolution]. It indicates that a type may be +used as a method receiver; that is, the type of a `self` parameter for a +method. There is a blanket implementation of `Receiver` for all `T: Deref`, +so it's rare to implement `Receiver` directly: you'd only normally do this +for smart pointer types which for some reason can't implement `Deref`. ## `Drop` @@ -145,6 +153,7 @@ These implicit `Sized` bounds may be relaxed by using the special `?Sized` bound [`DerefMut`]: std::ops::DerefMut [`Pin

`]: std::pin::Pin [`Rc`]: std::rc::Rc +[`Receiver`]: std::ops::Receiver [`RefUnwindSafe`]: std::panic::RefUnwindSafe [`Termination`]: std::process::Termination [`UnwindSafe`]: std::panic::UnwindSafe