Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arbitrary self types v2: update reference. #1699

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

adetaylor
Copy link
Contributor

@rustbot rustbot added the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label Dec 19, 2024
@adetaylor
Copy link
Contributor Author

@rustbot label +S-waiting-on-author -S-waiting-on-review

@rustbot rustbot added S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. and removed S-waiting-on-review Status: The marked PR is awaiting review from a maintainer labels Dec 19, 2024
@Skgland
Copy link

Skgland commented Dec 21, 2024

Wouldn't the point

  • [Methods] can take [Type<T>] as a receiver.

for Box<T>, Rc<T>, Arc<T> and Pin<T> no longer be special about these types with
the Receiver trait being stabilized? And as such that bullet point and in turn the latter three Types should be removed from the list?

https://github.com/rust-lang/reference/pull/1699/files#diff-90d122e8e582daf4ac75c86e4be63d9c91e7bc7cc6144bad4d62de7332eddf35R15-R29

@adetaylor
Copy link
Contributor Author

Wouldn't the point

  • [Methods] can take [Type<T>] as a receiver.

for Box<T>, Rc<T>, Arc<T> and Pin<T> no longer be special about these types with the Receiver trait being stabilized? And as such that bullet point and in turn the latter three Types should be removed from the list?

I agree, I'll remove that bit.

@rustbot

This comment has been minimized.

@adetaylor adetaylor force-pushed the arbitrary-self-types-v2 branch from c860df3 to e138cf7 Compare January 28, 2025 11:34
@adetaylor
Copy link
Contributor Author

I've pushed a couple of extra commits here to respond to review feedback - I suspect I should probably squash them before this is merged (?) but for now it's easier for folks to see what I changed.

@adetaylor adetaylor force-pushed the arbitrary-self-types-v2 branch from d641699 to 84f896f Compare January 28, 2025 11:51
Comment on lines +20 to +30
The first step is to build a list of types where we might find methods.
Obtain these by repeatedly [dereferencing][dereference] the receiver expression's type, adding each type encountered to the list, then finally attempting an [unsized coercion] at the end, and adding the result type if that is successful.
Then, for each candidate `T`, add `&T` and `&mut T` to the list immediately after `T`.
Then, for each candidate `T`, add `&T` and `&mut T` to the list immediately after `T`. While dereferencing, we don't use the normal `Deref` trait, but instead the `Receiver` trait: there is a blanket implementation of `Receiver` for all `T: Deref` so in practice this is often the same.

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]`.
For instance, if the receiver has type `Box<[i32;2]>`, then the contributing 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:
Some custom smart pointers may implement `Receiver` but not `Deref`. Imagine `MySmartPtr<T>: Receiver<Target=T>`: if the receiver type has `Box<MySmartPtr<SomeStruct>>` the contributing types will be `Box<MySmartPtr<SomeStruct>>`, `MySmartPtr<SomeStruct>` and `SomeStruct`.

Even though we assemble this list by following the chain of `Receiver` implementations, we keep a note of which steps can be reached by following the regular `Deref` chain. In the above example, that would be all but the last step. The items in the list reachable by the `Deref` chain are termed the "candidate types"; the full list reachable by the `Receiver` chain is called the "contributing types".

Then, for each _contributing_ type `T`, search for a [visible] method with a receiver of any _candidate_ type in the following places:
Copy link
Contributor

@traviscross traviscross Jan 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is better, but still some things we can improve:

  • We're inconsistently using the word "candidate". Toward the top, we talk about assembling the list of candidates (i.e. "for each candidate T, add ... to the list"), but we don't mean the list of "candidate types" as defined later, we mean the list of "contributing types". The word "candidate" is also used further below in a seemingly-inconsistent way.
  • We separately define this notion of "candidate types" from "contributing types", but we don't say why or use the list of candidate types for anything as far as I can tell. It's a bit odd to define this separately if it has no semantic relevance to the language. If there is some semantic relevance, we should describe it. If it's only of implementation relevance, then it's probably a better fit for the dev guide.
  • We're no longer stating our terms upfront. That's what the bit you removed about "The first step is to build a list of candidate receiver types" was doing -- it introduced that term, then described how we built that list. The text now says "the contributing types will be..." without first introducing that this is a special term and we're building a list of these things.
  • Talking about repeated dereferencing and then saying, "well, really it's not dereferencing but this other thing" is a bit odd. It's probably better to just directly describe that we're following the chain of receiver targets.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed with all your points other than this one:

We separately define this notion of "candidate types" from "contributing types", but we don't say why or use the list of candidate types for anything as far as I can tell. It's a bit odd to define this separately if it has no semantic relevance to the language. If there is some semantic relevance, we should describe it. If it's only of implementation relevance, then it's probably a better fit for the dev guide.

It is of semantic relevance - it says this, which you may have overlooked:

Then, for each contributing type T, search for a visible method with a receiver of any candidate type in the following places:

I'll have another crack at it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks. Did miss that bit.

Comment on lines +62 to +63
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`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably remove this bit about it being rare and instead describe affirmatively why Receiver can be implemented but Deref cannot in some cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants