]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | # Method-call expressions |
2 | ||
2c00a5a8 XL |
3 | A _method call_ consists of an expression (the *receiver*) followed by a single |
4 | dot, an [identifier], and a parenthesized expression-list. Method calls are | |
83c7162d XL |
5 | resolved to associated [methods] on specific traits, either statically |
6 | dispatching to a method if the exact `self`-type of the left-hand-side is known, | |
7 | or dynamically dispatching if the left-hand-side expression is an indirect | |
8 | [trait object](types.html#trait-objects). | |
ea8adc8c XL |
9 | |
10 | ```rust | |
11 | let pi: Result<f32, _> = "3.14".parse(); | |
12 | let log_pi = pi.unwrap_or(1.0).log(2.72); | |
13 | # assert!(1.14 < log_pi && log_pi < 1.15) | |
14 | ``` | |
15 | ||
2c00a5a8 XL |
16 | When looking up a method call, the receiver may be automatically dereferenced or |
17 | borrowed in order to call a method. This requires a more complex lookup process | |
18 | than for other functions, since there may be a number of possible methods to | |
19 | call. The following procedure is used: | |
20 | ||
21 | The first step is to build a list of candidate receiver types. Obtain | |
22 | these by repeatedly [dereferencing][dereference] the receiver expression's type, | |
23 | adding each type encountered to the list, then finally attempting an [unsized | |
24 | coercion] at the end, and adding the result type if that is successful. Then, | |
25 | for each candidate `T`, add `&T` and `&mut T` to the list immediately after `T`. | |
26 | ||
27 | For instance, if the receiver has type `Box<[i32;2]>`, then the candidate types | |
28 | will be `Box<[i32;2]>`, `&Box<[i32;2]>`, `&mut Box<[i32;2]>`, `[i32; 2]` (by | |
29 | dereferencing), `&[i32; 2]`, `&mut [i32; 2]`, `[i32]` (by unsized coercion), | |
30 | `&[i32]`, and finally `&mut [i32]`. | |
31 | ||
32 | Then, for each candidate type `T`, search for a [visible] method with | |
33 | a receiver of that type in the following places: | |
ea8adc8c | 34 | |
2c00a5a8 XL |
35 | 1. `T`'s inherent methods (methods implemented directly on `T`). |
36 | 1. Any of the methods provided by a [visible] trait implemented by `T`. If `T` | |
37 | is a type parameter, methods provided by trait bounds on `T` are looked up | |
38 | first. Then all remaining methods in scope are looked up. | |
ea8adc8c | 39 | |
2c00a5a8 XL |
40 | > Note: the lookup is done for each type in order, which can occasionally lead |
41 | > to surprising results. The below code will print "In trait impl!", because | |
42 | > `&self` methods are looked up first, the trait method is found before the | |
43 | > struct's `&mut self` method is found. | |
44 | > | |
45 | > ```rust | |
46 | > struct Foo {} | |
47 | > | |
48 | > trait Bar { | |
49 | > fn bar(&self); | |
50 | > } | |
51 | > | |
52 | > impl Foo { | |
53 | > fn bar(&mut self) { | |
54 | > println!("In struct impl!") | |
55 | > } | |
56 | > } | |
57 | > | |
58 | > impl Bar for Foo { | |
59 | > fn bar(&self) { | |
60 | > println!("In trait impl!") | |
61 | > } | |
62 | > } | |
63 | > | |
64 | > fn main() { | |
65 | > let mut f = Foo{}; | |
66 | > f.bar(); | |
67 | > } | |
68 | > ``` | |
69 | ||
70 | If this results in multiple possible candidates, then it is an error, and the | |
71 | receiver must be [converted][disambiguate call] to an appropriate receiver type | |
72 | to make the method call. | |
73 | ||
74 | This process does not take into account the mutability or lifetime of the | |
75 | receiver, or whether a method is `unsafe`. Once a method is looked up, if it | |
76 | can't be called for one (or more) of those reasons, the result is a compiler | |
77 | error. | |
78 | ||
79 | If a step is reached where there is more than one possible method, such as where | |
80 | generic methods or traits are considered the same, then it is a compiler | |
81 | error. These cases require a [disambiguating function call syntax] for method | |
ea8adc8c | 82 | and function invocation. |
ff7c6d11 | 83 | |
2c00a5a8 XL |
84 | > Warning: For [trait objects], if there is an inherent method of the same name |
85 | > as a trait method, it will give a compiler error when trying to call the | |
86 | > method in a method call expression. Instead, you can call the method using | |
87 | > [disambiguating function call syntax], in which case it calls the trait | |
88 | > method, not the inherent method. There is no way to call the inherent method. | |
89 | > Just don't define inherent methods on trait objects with the same name a trait | |
90 | > method and you'll be fine. | |
91 | ||
92 | [IDENTIFIER]: identifiers.html | |
93 | [visible]: visibility-and-privacy.html | |
94 | [array]: types.html#array-and-slice-types | |
95 | [trait objects]: types.html#trait-objects | |
96 | [disambiguate call]: expressions/call-expr.html#disambiguating-function-calls | |
97 | [dereference]: expressions/operator-expr.html#the-dereference-operator | |
83c7162d | 98 | [methods]: items/associated-items.html#methods |