method-lookup.md improvements (#1296)

This commit is contained in:
Matthew Woodcraft 2022-04-11 15:29:48 +01:00 committed by GitHub
parent cd09c7d4b7
commit de2dd7ce06
1 changed files with 13 additions and 12 deletions

View File

@ -79,33 +79,34 @@ behavior should be reconsidered in light of where clauses.
TODO: Is this FIXME still accurate? TODO: Is this FIXME still accurate?
**Extension candidates** are derived from imported traits. If I have **Extension candidates** are derived from imported traits. If I have
the trait `ToString` imported, and I call `to_string()` on a value of the trait `ToString` imported, and I call `to_string()` as a method,
type `T`, then we will go off to find out whether there is an impl of then we will list the `to_string()` definition in each impl of
`ToString` for `T`. These kinds of method calls are called "extension `ToString` as a candidate. These kinds of method calls are called
methods". They can be defined in any crate, not only the one that "extension methods".
defined `T`. Furthermore, you must import the trait to call such a
method.
So, let's continue our example. Imagine that we were calling a method So, let's continue our example. Imagine that we were calling a method
`foo` with the receiver `Rc<Box<[T; 3]>>` and there is a trait `Foo` `foo` with the receiver `Rc<Box<[T; 3]>>` and there is a trait `Foo`
that defines it with `&self` for the type `Rc<U>` as well as a method that defines it with `&self` for the type `Rc<U>` as well as a method
on the type `Box` that defines `Foo` but with `&mut self`. Then we on the type `Box` that defines `foo` but with `&mut self`. Then we
might have two candidates: might have two candidates:
- `&Rc<Box<[T; 3]>>` from the impl of `Foo` for `Rc<U>` where `U=Box<[T; 3]>` - `&Rc<U>` as an extension candidate
- `&mut Box<[T; 3]>>` from the inherent impl on `Box<U>` where `U=[T; 3]` - `&mut Box<U>` as an inherent candidate
### Candidate search ### Candidate search
Finally, to actually pick the method, we will search down the steps, Finally, to actually pick the method, we will search down the steps,
trying to match the receiver type against the candidate types. At trying to match the receiver type against the candidate types. At
each step, we also consider an auto-ref and auto-mut-ref to see whether each step, we also consider an auto-ref and auto-mut-ref to see whether
that makes any of the candidates match. We pick the first step where that makes any of the candidates match. For each resulting receiver
we find a match. type, we consider inherent candidates before extension candidates.
If there are multiple matching candidates in a group, we report an
error, except that multiple impls of the same trait are treated as a
single match. Otherwise we pick the first match we find.
In the case of our example, the first step is `Rc<Box<[T; 3]>>`, In the case of our example, the first step is `Rc<Box<[T; 3]>>`,
which does not itself match any candidate. But when we autoref it, we which does not itself match any candidate. But when we autoref it, we
get the type `&Rc<Box<[T; 3]>>` which does match. We would then get the type `&Rc<Box<[T; 3]>>` which matches `&Rc<U>`. We would then
recursively consider all where-clauses that appear on the impl: if recursively consider all where-clauses that appear on the impl: if
those match (or we cannot rule out that they do), then this is the those match (or we cannot rule out that they do), then this is the
method we would pick. Otherwise, we would continue down the series of method we would pick. Otherwise, we would continue down the series of