1
1
# Method-call expressions
2
2
3
- A _ method call_ consists of an expression followed by a single dot, an
4
- [ identifier] , and a parenthesized expression-list. Method
5
- calls are resolved to methods on specific traits, either statically dispatching
6
- to a method if the exact ` self ` -type of the left-hand-side is known, or
7
- dynamically dispatching if the left-hand-side expression is an indirect [ trait
8
- object] ( types.html#trait-objects ) . Method call expressions will automatically
9
- take a shared or mutable borrow of the receiver if needed.
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
5
+ resolved to methods on specific traits, either statically dispatching to a
6
+ method if the exact ` self ` -type of the left-hand-side is known, or dynamically
7
+ dispatching if the left-hand-side expression is an indirect [ trait
8
+ object] ( types.html#trait-objects ) .
10
9
11
10
``` rust
12
11
let pi : Result <f32 , _ > = " 3.14" . parse ();
13
12
let log_pi = pi . unwrap_or (1.0 ). log (2.72 );
14
13
# assert! (1.14 < log_pi && log_pi < 1.15 )
15
14
```
16
15
17
- When resolving method calls on an expression of type ` A ` , Rust will use the
18
- following order, only looking at methods that are [ visible] . If the type of ` A `
19
- is a type parameter or ` Self ` in a trait definitition then steps 2-4 first
20
- consider traits from bounds on the type paramter, then the traits that are in
21
- scope. For other types, only the traits that are in scope are considered.
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:
22
20
23
- 1 . Inherent methods, with receiver of type ` A ` , ` &A ` , ` &mut A ` .
24
- 1 . Trait methods with receiver of type ` A ` .
25
- 1 . Trait methods with receiver of type ` &A ` .
26
- 1 . Trait methods with receiver of type ` &mut A ` .
27
- 1 . If it's possible, Rust will then repeat steps 1-5 with
28
- ` <A as std::ops::Deref>::Target ` , and insert a dereference operator.
29
- 1 . If ` A ` is now an [ array] type, then repeat steps 1-4 with the corresponding
30
- slice type.
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 ` .
31
26
32
- Note: In steps 1-4, the receiver is used, not the type of ` Self ` nor the
33
- type of ` A ` . For example:
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] ` .
34
31
35
- ``` rust,ignore
36
- // `Self` is `&A`, receiver is `&A`.
37
- impl<'a> Trait for &'a A {
38
- fn method(self) {}
39
- }
40
- // If `A` is `&B`, then `Self` is `B` and the receiver is `A`.
41
- impl B {
42
- fn method(&self) {}
43
- }
44
- ```
32
+ Then, for each candidate type ` T ` , search for a [ visible] method with
33
+ a receiver of that type in the following places:
34
+
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.
39
+
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 .
45
73
46
- Another note: this process does not use the mutability or lifetime of the
47
- receiver, or whether ` unsafe ` methods can currently be called to resolve
48
- methods. These constraints instead lead to compiler errors.
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 .
49
78
50
79
If a step is reached where there is more than one possible method , such as where
51
80
generic methods or traits are considered the same , then it is a compiler
@@ -64,4 +93,5 @@ and function invocation.
64
93
[visible ]: visibility - and - privacy . html
65
94
[array ]: types . html#array - and - slice - types
66
95
[trait objects ]: types . html#trait - objects
67
- [ disambiguating function call syntax ] : expressions/call-expr.html#disambiguating-function-calls
96
+ [disambiguate call ]: expressions / call - expr . html#disambiguating - function - calls
97
+ [dereference ]: expressions / operator - expr . html#the - dereference - operator
0 commit comments