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

Method call reference: major rewrite #1725

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

adetaylor
Copy link
Contributor

@adetaylor adetaylor commented Jan 30, 2025

This section of the reference has been oversimplistic for some time (#1018 and #1534) and various rewrites have been attempted (e.g. #1394, #1432). Here's another attempt!

My approach here is:

  • Stop trying to keep it short and concise
  • Document what actually happens in the code, step by step

This does result in a long explanation, because we're trying to document nearly 2400 lines of code in probe.rs, but doing otherwise feels as though we'll continue to run into criticisms of oversimplification.

This rewrite documents the post-arbitrary-self-types v2 situation, i.e. it assumes rust-lang/rust#135881 has landed. We should not merge this until or unless that lands.

This PR was inspired by discussion in #1699. If we go ahead with this approach, #1699 becomes irrelevant. There was also discussion at rust-lang/cargo#15117 (comment)

Tracking:

This section of the reference has been oversimplistic for some time (rust-lang#1018
and rust-lang#1534) and various rewrites have been attempted (e.g. rust-lang#1394, rust-lang#1432).
Here's another attempt!

My approach here is:
* Stop trying to keep it short and concise
* Document what actually happens in the code, step by step

This does result in a long explanation, because we're trying to document
nearly 2400 lines of code in `probe.rs`, but doing otherwise feels
as though we'll continue to run into criticisms of oversimplification.

This rewrite documents the post-arbitrary-self-types v2 situation,
i.e. it assumes rust-lang/rust#135881 has
landed. We should not merge this until or unless that lands.

This PR was inspired by discussion in rust-lang#1699. If we go ahead with this
approach, rust-lang#1699 becomes irrelevant. There was also discussion at
rust-lang/cargo#15117 (comment)
@rustbot rustbot added the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label Jan 30, 2025
@nikomatsakis nikomatsakis self-assigned this Jan 30, 2025
@adetaylor adetaylor marked this pull request as ready for review January 30, 2025 18:58
Copy link
Contributor

@madsmtm madsmtm left a comment

Choose a reason for hiding this comment

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

Fully agree that it's better to list this out in detail than trying to condense it down to unreadable, and what you've written here is phenomenal!

src/expressions/method-call-expr.md Outdated Show resolved Hide resolved
src/expressions/method-call-expr.md Outdated Show resolved Hide resolved
src/expressions/method-call-expr.md Show resolved Hide resolved
src/expressions/method-call-expr.md Show resolved Hide resolved
Comment on lines +108 to +111
* And finally, a method with a `Pin` that's reborrowed, if the `pin_ergonomics`
feature is enabled.
* First for inherent methods
* Then for extension methods
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't generally document unstable features, but this is the kind of case that makes me pretty sad about taking it out, as the comprehensiveness here is nice. Wish we had a way to conditionalize this somehow.

cc @nikomatsakis as an example for us to think about.

@traviscross
Copy link
Contributor

Overall, this is fantastic. Very much an improvement. Thanks @adetaylor.

@traviscross traviscross added the S-waiting-on-stabilization Waiting for a stabilization PR to be merged in the main Rust repository label Jan 31, 2025
@rustbot
Copy link
Collaborator

rustbot commented Jan 31, 2025

☔ The latest upstream changes (possibly 4249fb4) made this pull request unmergeable. Please resolve the merge conflicts.

src/expressions/method-call-expr.md Outdated Show resolved Hide resolved
src/expressions/method-call-expr.md Outdated Show resolved Hide resolved
src/expressions/method-call-expr.md Outdated Show resolved Hide resolved
src/expressions/method-call-expr.md Outdated Show resolved Hide resolved
src/expressions/method-call-expr.md Outdated Show resolved Hide resolved
@mattheww
Copy link
Contributor

mattheww commented Feb 3, 2025

Note there's another description of the method lookup process in the
rustc-dev-guide.

@mattheww
Copy link
Contributor

mattheww commented Feb 3, 2025

One thing that makes this business difficult to document is that method lookup happens when type inference is not yet complete (and the results of method lookup participate in type inference).

All the writeups I've seen gloss over this by writing "the receiver type" and then proceeding to describe what happens as if that type was fully determined.

I'm not sure how much detail it makes sense to go into on this page as long as the Reference has very little to say in general about type inference. But I think it might be worth mentioning that:

  • At this point the receiver type might be something like Vec<?>, which I think explains how the "If there are multiple candidates from traits, they may in fact be identical" case can happen.

  • If the type isn't constrained at all by the code coming before the method call, method resolution will just give up (even if there's only one possible type for which the method call could work).

@mattheww
Copy link
Contributor

mattheww commented Feb 3, 2025

It might also be worth noting explicitly that the types of parameters in the method call expression aren't taken into account in method resolution. Even the number of parameters is ignored. So the following won't compile, because the method from NoParameter is found earlier in the picking process even though it's "obviously" the wrong one.

trait NoParameter {
    fn method(self);
}

trait OneParameter {
    fn method(&self, jj: i32);
}

impl NoParameter for char {
    fn method(self) {}
}

impl OneParameter for char {
    fn method(&self, jj: i32) {}
}

fn f() {
    'x'.method(123);
}

@obi1kenobi
Copy link
Member

Wow, this example is very surprising to me!

With my "cargo-semver-checks maintainer" hat on, it's extremely useful to have someplace where these details are written up with examples like this. The better I can understand these nuances, the better our rules for discovering breakage will be.

I will leave to you all the question of whether the reference or some other location is the best place to document these behaviors.

@adetaylor
Copy link
Contributor Author

It might also be worth noting explicitly that the types of parameters in the method call expression aren't taken into account in method resolution.

Agreed - I added your example in 687a52b.

@adetaylor
Copy link
Contributor Author

@mattheww regarding

One thing that makes this business difficult to document is that method lookup happens when type inference is not yet complete (and the results of method lookup participate in type inference).

I agree that it would be good to explain that here, but I'd prefer it be done in a separate PR - this one is already ambitious enough, and I don't think it makes that situation worse.

@mattheww
Copy link
Contributor

mattheww commented Feb 8, 2025

Yes, it would be better to get this merged and think about improving it later.

I think with the Reference in its current state there's an argument that this part should just be omitted (if it can't happen in a model where the full type of the receiver is known):

If there are multiple candidates from traits, they may in fact be identical, and the picking operation collapses them to a single pick to avoid reporting conflicts

But I'd certainly have no objection to leaving that question for another time.

@adetaylor
Copy link
Contributor Author

I'm not sure whether that's the only case where the candidates may turn out to be identical - I'll try to work it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: The marked PR is awaiting review from a maintainer S-waiting-on-stabilization Waiting for a stabilization PR to be merged in the main Rust repository
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants