For now, this reference is a best-effort document. We strive for validity and completeness, but are not yet there. In the future, the docs and lang teams will work together to figure out how best to do this. Until then, this is a best-effort attempt. If you find something wrong or missing, file an issue or send in a pull request.

Method-call expressions

A method call consists of an expression followed by a single dot, an identifier, and a parenthesized expression-list. Method calls are resolved to 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. Method call expressions will automatically take a shared or mutable borrow of the receiver if needed.

# #![allow(unused_variables)]
#fn main() {
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)

When resolving method calls on an expression of type A, Rust will use the following order, only looking at methods that are visible. If the type of A is a type parameter or Self in a trait definitition then steps 2-4 first consider traits from bounds on the type paramter, then the traits that are in scope. For other types, only the traits that are in scope are considered.

  1. Inherent methods, with receiver of type A, &A, &mut A.
  2. Trait methods with receiver of type A.
  3. Trait methods with receiver of type &A.
  4. Trait methods with receiver of type &mut A.
  5. If it's possible, Rust will then repeat steps 1-5 with <A as std::ops::Deref>::Target, and insert a dereference operator.
  6. If A is now an array type, then repeat steps 1-4 with the corresponding slice type.

Note: that in steps 1-4 the receiver is used, not the type of Self nor the type of A. For example

// `Self` is `&A`, receiver is `&A`.
impl<'a> Trait for &'a A {
    fn method(self) {}
// If `A` is `&B`, then `Self` is `B` and the receiver is `A`.
impl B {
    fn method(&self) {}

Another note: this process does not use the mutability or lifetime of the receiver, or whether unsafe methods can currently be called to resolve methods. These constraints instead lead to compiler errors.

If a step is reached where there is more than one possible method (where generic methods or traits are considered the same), then it is a compiler error. These cases require a more specific syntax. for method and function invocation.