|  | r[expr.method] | 
|  | # Method-call expressions | 
|  |  | 
|  | r[expr.method.syntax] | 
|  | ```grammar,expressions | 
|  | MethodCallExpression -> Expression `.` PathExprSegment `(`CallParams? `)` | 
|  | ``` | 
|  |  | 
|  | r[expr.method.intro] | 
|  | A _method call_ consists of an expression (the *receiver*) followed by a single dot, an expression path segment, and a parenthesized expression-list. | 
|  |  | 
|  | r[expr.method.target] | 
|  | Method calls are resolved to associated [methods] on specific traits, either statically dispatching to a method if the exact `self`-type of the left-hand-side is known, or dynamically dispatching if the left-hand-side expression is an indirect [trait object](../types/trait-object.md). | 
|  |  | 
|  | ```rust | 
|  | let pi: Result<f32, _> = "3.14".parse(); | 
|  | let log_pi = pi.unwrap_or(1.0).log(2.72); | 
|  | # assert!(1.14 < log_pi && log_pi < 1.15) | 
|  | ``` | 
|  |  | 
|  | r[expr.method.autoref-deref] | 
|  | When looking up a method call, the receiver may be automatically dereferenced or borrowed in order to call a method. | 
|  | This requires a more complex lookup process than for other functions, since there may be a number of possible methods to call. | 
|  | The following procedure is used: | 
|  |  | 
|  | r[expr.method.candidate-receivers] | 
|  | The first step is to build a list of candidate receiver types. | 
|  | Obtain these by repeatedly [dereferencing][dereference] the receiver expression's 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. | 
|  |  | 
|  | r[expr.method.candidate-receivers-refs] | 
|  | Then, for each candidate `T`, add `&T` and `&mut T` to the list immediately after `T`. | 
|  |  | 
|  | For instance, if the receiver has type `Box<[i32;2]>`, then the candidate types will be `Box<[i32;2]>`, `&Box<[i32;2]>`, `&mut Box<[i32;2]>`, `[i32; 2]` (by dereferencing), `&[i32; 2]`, `&mut [i32; 2]`, `[i32]` (by unsized coercion), `&[i32]`, and finally `&mut [i32]`. | 
|  |  | 
|  | r[expr.method.candidate-search] | 
|  | Then, for each candidate type `T`, search for a [visible] method with 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 [visible] trait implemented by `T`. | 
|  | If `T` is a type parameter, methods provided by trait bounds on `T` are looked up first. | 
|  | Then all remaining methods in scope are looked up. | 
|  |  | 
|  | > [!NOTE] | 
|  | > The lookup is done for each type in order, which can occasionally lead 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. | 
|  | > | 
|  | > ```rust | 
|  | > struct Foo {} | 
|  | > | 
|  | > trait Bar { | 
|  | >   fn bar(&self); | 
|  | > } | 
|  | > | 
|  | > impl Foo { | 
|  | >   fn bar(&mut self) { | 
|  | >     println!("In struct impl!") | 
|  | >   } | 
|  | > } | 
|  | > | 
|  | > impl Bar for Foo { | 
|  | >   fn bar(&self) { | 
|  | >     println!("In trait impl!") | 
|  | >   } | 
|  | > } | 
|  | > | 
|  | > fn main() { | 
|  | >   let mut f = Foo{}; | 
|  | >   f.bar(); | 
|  | > } | 
|  | > ``` | 
|  |  | 
|  | r[expr.method.ambiguous-target] | 
|  | If this results in multiple possible candidates, then it is an error, and the receiver must be [converted][disambiguate call] to an appropriate receiver type to make the method call. | 
|  |  | 
|  | r[expr.method.receiver-constraints] | 
|  | This 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, if it can't be called for one (or more) of those reasons, the result is a compiler error. | 
|  |  | 
|  | r[expr.method.ambiguous-search] | 
|  | If a step is reached where there is more than one possible method, such as where generic methods or traits are considered the same, then it is a compiler error. | 
|  | These cases require a [disambiguating function call syntax] for method and function invocation. | 
|  |  | 
|  | r[expr.method.edition2021] | 
|  | > [!EDITION-2021] | 
|  | > Before the 2021 edition, during the search for visible methods, if the candidate receiver type is an [array type], methods provided by the standard library [`IntoIterator`] trait are ignored. | 
|  | > | 
|  | > The edition used for this purpose is determined by the token representing the method name. | 
|  | > | 
|  | > This special case may be removed in the future. | 
|  |  | 
|  | > [!WARNING] | 
|  | > For [trait objects], if there is an inherent method of the same name as a trait method, it will give a compiler error when trying to call the method in a method call expression. | 
|  | > Instead, you can call the method using [disambiguating function call syntax], in which case it calls the trait method, not the inherent method. | 
|  | > There is no way to call the inherent method. | 
|  | > Just don't define inherent methods on trait objects with the same name as a trait method and you'll be fine. | 
|  |  | 
|  | [visible]: ../visibility-and-privacy.md | 
|  | [array type]: ../types/array.md | 
|  | [trait objects]: ../types/trait-object.md | 
|  | [disambiguate call]: call-expr.md#disambiguating-function-calls | 
|  | [disambiguating function call syntax]: call-expr.md#disambiguating-function-calls | 
|  | [dereference]: operator-expr.md#the-dereference-operator | 
|  | [methods]: ../items/associated-items.md#methods | 
|  | [unsized coercion]: ../type-coercions.md#unsized-coercions | 
|  | [`IntoIterator`]: std::iter::IntoIterator |