-
Notifications
You must be signed in to change notification settings - Fork 537
Adjust receiver lookup to match the actual impl #190
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
Conversation
As a part of this, remove the reference to coerce_inner and replace it with a proper description of unsized coercions. That description will have to be updated later when more of the unsized work stabilizes. Closes rust-lang#62.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly nits. Otherwise looking good.
src/expressions/method-call-expr.md
Outdated
fn method(self) {} | ||
When resolving method calls on an expression of type `A`, Rust looks up methods | ||
both on the type itself and the traits in implements. Additionally, unlike with | ||
non-method function calls, the `self` parameter is special and may be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like calling them "non-method function calls", but I don't know of a better name. "standard" and "regular" both make it sounds like method calls are non-standard or irregular. Any ideas here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might also want to link to that expression kind from here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about just "other"?
src/expressions/method-call-expr.md
Outdated
When resolving method calls on an expression of type `A`, Rust looks up methods | ||
both on the type itself and the traits in implements. Additionally, unlike with | ||
non-method function calls, the `self` parameter is special and may be | ||
automatically dereferenced in order to resolve it. Rust uses the following |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything in this document is about Rust. Mentioning it should be avoided, I think. Better wording would be "The following is the process/procedure to resolve which method to call."
src/expressions/method-call-expr.md
Outdated
automatically dereferenced in order to resolve it. Rust uses the following | ||
process to resolve method calls. | ||
|
||
First, Rust will attempt to build a list of candidate receiver types. It obtains |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"First, attempt to" & "Obtain these"
src/expressions/method-call-expr.md
Outdated
these by repeatedly [dereferencing][dereference] the 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`, Rust adds `&T` and `&mut T` to the list immediately afterward. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More "Rust" removal. Also, clarify after what to add after. Currently it's ambiguous as to whether it's the end of the list or after the T
. Though the example clarifies it.
"for each candidate T
, add &T
and &mut T
to the list immediately after T
."
src/expressions/method-call-expr.md
Outdated
end, and adding the result type if that is successful. Then, for each candidate | ||
`T`, Rust adds `&T` and `&mut T` to the list immediately afterward. | ||
|
||
So, for instance, if `A` is `Box<[i32;2]>`, then the candidate types will be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The So, for instance
is two leading clauses. I would drop the "So". Also, we want to use "example" for examples, not "instance". (Later I want to actually put examples into their own <div>.
src/expressions/method-call-expr.md
Outdated
a receiver of that type in the following places: | ||
|
||
1. `T`'s inherent methods (methods implemented directly on `T`). | ||
1. Any of the methods provided by a trait implemented by `T`. If `T` is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we say "visible trait" here? Do we define that term anywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do, the [visible] is a link to the visibility page. You're right that it should say visible trait, I think, so I can add that in.
src/expressions/method-call-expr.md
Outdated
methods from the trait constraints on `T` are available for lookup. If `T` is | ||
not, then methods from any in-scope trait are available. | ||
|
||
Note that the lookup is done for each type in order, which can occasionally lead |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Colon after "Note". Entire note and example should be in blockquotes. Could raise to a "Warning:" even.
src/expressions/method-call-expr.md
Outdated
receiver must be [converted][disambiguate call] to an appropriate receiver type | ||
to make the method call. | ||
|
||
The lookup process does not take into account the mutability or lifetime of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"This process"
src/expressions/method-call-expr.md
Outdated
to make the method call. | ||
|
||
The lookup process does not take into account the mutability or lifetime of the | ||
receiver, or whether a method is `unsafe`. Once a method is looked up. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ending sentence here is a sentence fragment. We've lost the part where it's a compiler error if the listed constraints fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, that was what the fragment was supposed to be. Thanks.
src/expressions/method-call-expr.md
Outdated
|
||
First, Rust will attempt to build a list of candidate receiver types. It obtains | ||
these by repeatedly [dereferencing][dereference] the type, adding each type | ||
encountered to the list, then finally attempting an [unsized coercion] at the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's only array to slice unsizing coercions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll verify this and then update if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like even a CoerceUnsized coercion can work:
https://play.rust-lang.org/?gist=a08eb003e02c3f9abc0771cd7017b794&version=stable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're going from &[i32; 3]
to &[i32]
, which is exactly the case that I'm saying works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Err, right. Niko said it could be any unsized conversion, but I guess CoerceUnsized
won't ever happen here, because it'll just get dereferenced and the underlying conversion applied. Likewise I think supertrait object conversion is impossible since it'll just find the method on the subtrait. The last option is unsized struct conversion, but that seems like it can't be applied here: https://play.rust-lang.org/?gist=1aa827380405e1a287b275fe0f83b69a&version=stable
Is that example correct to demonstrate that the unsized struct conversion doesn't work here? @nikomatsakis, is this the expected behaviour?
* `[T; n]` to `[T]`. | ||
|
||
* `T` to `U`, when `U` is a trait object type and either `T` implements `U` or | ||
`T` is a trait object for a subtrait of `U`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also the third case in the Unsize docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left that out since it isn't yet stabilized. Should I put it in anyway?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The coercion is stable, it's just the trait that isn't.
src/expressions/method-call-expr.md
Outdated
1. `T`'s inherent methods (methods implemented directly on `T`). | ||
1. Any of the methods provided by a trait implemented by `T`. If `T` is | ||
a type parameter (including the `Self` parameter of a trait), then only | ||
methods from the trait constraints on `T` are available for lookup. If `T` is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In scope traits are still checked, methods from traits in bounds are treated as inherent methods so get looked at first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, ok. How can an in scope trait apply to a bounded type parameter? Does it have to be declared locally?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trait A {
fn foo(&self) {}
}
impl<U> A for U {}
fn bar<T>(t: T) {
t.foo(); // OK, calls A::foo
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh, right. Thanks!
Do you prefer to have changes rebased into a single commit? |
It's useful to have multiple commits while editing, especially for large sections of new prose, but it's always nice to just have a single commit for it after editing. Ultimately, there's no official policy on this for the reference, as far as I know. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit more awake on this review than the last one. These are all things I can do myself, so if you ever feel like we're going in circles too much, and just want me to merge, I can do so.
With method call receiver not defined anywhere, I sort of want to do another PR on this section anyways.
src/expressions/method-call-expr.md
Outdated
process to resolve method calls. | ||
|
||
First, Rust will attempt to build a list of candidate receiver types. It obtains | ||
When resolving method calls on an expression of type `A`, that expression will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only use A
twice now, and it's sort of useless to name it. It'd be nice to remove it. Especially since I think the other usage would read better without it.
src/expressions/method-call-expr.md
Outdated
|
||
First, Rust will attempt to build a list of candidate receiver types. It obtains | ||
When resolving method calls on an expression of type `A`, that expression will | ||
be the `self` parameter. This parameter is special and, unlike with other |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"be the self
parameter on the called method."
A second reading of this, I would also get rid of everything from "is special" to "or other functions", unless you feel like it's worth emphasizing that this behavior only applies to the method receiver. Which I noticed isn't really defined either.
src/expressions/method-call-expr.md
Outdated
|
||
So, for instance, if `A` is `Box<[i32;2]>`, then the candidate types will be | ||
For instance, if `A` is `Box<[i32;2]>`, then the candidate types will be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the other usage of A
. I think it would read better without referring to A
and just said "if the method receiver is of type Box<[i32; 2]>".
src/expressions/method-call-expr.md
Outdated
to surprising results. The below code will print "In trait impl!", because | ||
`&self` methods are looked up first, the trait method is found before the | ||
struct's `&mut self` method is found. | ||
Note: the lookup is done for each type in order, which can occasionally lead |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This Note and example should still all be in blockquotes. You can do so by starting each line with a >
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm used to four spaces for blockquote. I'll change to >
though. And sorry about the example.
src/type-coercions.md
Outdated
cases where other coercions are not, as described above. They can still happen | ||
anywhere else a coercion can occur. | ||
|
||
Two traits, `Unsized` and `CoerceUnsized`, are used to assist in this process |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure these are actual links. It'd be ../std/marker/trait.Unsize.html
and ../std/ops/trait.CoerceUnsized.html
respectively.
The "expose it for library use" part is definitely unstable and should be removed for now.
LGTM. Though I don't know if @matthewjasper 's concerns are addressed. @matthewjasper, are you good with this PR? |
Comment about which unsizing coercions are actually performed is still relevant, but this is generally an improvement. I'm happy to have this merged with an issue created (either here or on the main repo) if we can't reach a decision now. |
Alright, merging it in. @matthewjasper I'm not entirely sure what the details are about unsizing concerns, so could you file the issue? @alercah 💟 |
As a part of this, remove the reference to coerce_inner and replace it
with a proper description of unsized coercions. That description will
have to be updated later when more of the unsized work stabilizes.
Please review this for correctness; I was mostly working off of the description in #62, the DST RFC, and some personal test examples.
And of course, if there's anything that can be done to include clarity (such as more examples), I can do that too.