Skip to content

Commit 87bea5d

Browse files
author
Alexis Hunt
committed
Review feedback.
1 parent 8cc56ae commit 87bea5d

File tree

2 files changed

+44
-21
lines changed

2 files changed

+44
-21
lines changed

src/expressions/method-call-expr.md

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,36 @@ let log_pi = pi.unwrap_or(1.0).log(2.72);
1414
# assert!(1.14 < log_pi && log_pi < 1.15)
1515
```
1616

17-
When resolving method calls on an expression of type `A`, Rust looks up methods
18-
both on the type itself and the traits in implements. Additionally, unlike with
19-
non-method function calls, the `self` parameter is special and may be
20-
automatically dereferenced in order to resolve it. Rust uses the following
21-
process to resolve method calls.
22-
23-
First, Rust will attempt to build a list of candidate receiver types. It obtains
17+
When resolving method calls on an expression of type `A`, that expression will
18+
be the `self` parameter. This parameter is special and, unlike with other
19+
parameters to methods or other functions, may be automatically dereferenced or
20+
borrowed in order to call a method. This requires a more complex lookup process,
21+
since there may be a number of possible methods to call. The following procedure
22+
is used:
23+
24+
The first step is to build a list of candidate receiver types. Obtain
2425
these by repeatedly [dereferencing][dereference] the type, adding each type
2526
encountered to the list, then finally attempting an [unsized coercion] at the
2627
end, and adding the result type if that is successful. Then, for each candidate
27-
`T`, Rust adds `&T` and `&mut T` to the list immediately afterward.
28+
`T`, add `&T` and `&mut T` to the list immediately after `T`.
2829

29-
So, for instance, if `A` is `Box<[i32;2]>`, then the candidate types will be
30+
For instance, if `A` is `Box<[i32;2]>`, then the candidate types will be
3031
`Box<[i32;2]>`, `&Box<[i32;2]>`, `&mut Box<[i32;2]>`, `[i32; 2]` (by
3132
dereferencing), `&[i32; 2]`, `&mut [i32; 2]`, `[i32]` (by unsized coercion),
3233
`&[i32]`, and finally `&mut [i32]`.
3334

34-
Then, for each candidate type `T`, Rust will search for a [visible] method with
35+
Then, for each candidate type `T`, search for a [visible] method with
3536
a receiver of that type in the following places:
3637

3738
1. `T`'s inherent methods (methods implemented directly on `T`).
38-
1. Any of the methods provided by a trait implemented by `T`. If `T` is
39-
a type parameter (including the `Self` parameter of a trait), then only
40-
methods from the trait constraints on `T` are available for lookup. If `T` is
41-
not, then methods from any in-scope trait are available.
39+
1. Any of the methods provided by a [visible] trait implemented by `T`. If `T`
40+
is a type parameter, methods provided by trait bounds on `T` are looked up
41+
first. Then all remaining methods in scope are looked up.
4242

43-
Note that the lookup is done for each type in order, which can occasionally lead
44-
to surprising results. The below code will print "In trait impl!", because
45-
`&self` methods are looked up first, the trait method is found before the
46-
struct's `&mut self` method is found.
43+
Note: the lookup is done for each type in order, which can occasionally lead
44+
to surprising results. The below code will print "In trait impl!", because
45+
`&self` methods are looked up first, the trait method is found before the
46+
struct's `&mut self` method is found.
4747

4848
```rust
4949
struct Foo {}
@@ -74,8 +74,10 @@ If this results in multiple possible candidates, then it is an error, and the
7474
receiver must be [converted][disambiguate call] to an appropriate receiver type
7575
to make the method call.
7676

77-
The lookup process does not take into account the mutability or lifetime of the
78-
receiver, or whether a method is `unsafe`. Once a method is looked up.
77+
This process does not take into account the mutability or lifetime of the
78+
receiver, or whether a method is `unsafe`. Once a method is looked up, if it
79+
can't be called for one (or more) of those reasons, the result is a compiler
80+
error.
7981

8082
If a step is reached where there is more than one possible method, such as where
8183
generic methods or traits are considered the same, then it is a compiler

src/type-coercions.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,30 @@ Coercion is allowed between the following types:
152152

153153
The following coercions are called `unsized coercions`, since they
154154
relate to converting sized types to unsized types, and are permitted in a few
155-
cases where other coercions are not, as described above. They can still happen anywhere else a coercion can occur.
155+
cases where other coercions are not, as described above. They can still happen
156+
anywhere else a coercion can occur.
157+
158+
Two traits, `Unsized` and `CoerceUnsized`, are used to assist in this process
159+
and expose it for library use. The compiler following coercions are built-in
160+
and, if `T` can be coerced to `U` with one of the, then the compiler will
161+
provide an implementation of `Unsized<U>` for `T`:
156162

157163
* `[T; n]` to `[T]`.
158164

159165
* `T` to `U`, when `U` is a trait object type and either `T` implements `U` or
160166
`T` is a trait object for a subtrait of `U`.
167+
168+
* `Foo<..., T, ...>` to `Foo<..., U, ...>`, when:
169+
* `Foo` is a struct.
170+
* `T` implements `Unsized<U>`.
171+
* The last field of `Foo` has a type involving `T`.
172+
* If that field has type `Bar<T>`, then `Bar<T>` implements `Unsized<Bar<U>>`.
173+
* T is not part of the type of any other fields.
174+
175+
Additionally, a type `Foo<T>` can implement `CoerceUnsized<Foo<U>>` when `T`
176+
implements `Unsized<U>` or `CoerceUnsized<Foo<U>>`. This allows it to provide a
177+
unsized coercion to `Foo<U>`.
178+
179+
Note: While the definition of the unsized coercions and their implementation
180+
has been stabilized, the traits themselves are not yet stable and therefore
181+
can't be used directly in stable Rust.

0 commit comments

Comments
 (0)