Method Resolution & Operator Overload
Method calls are the expressions that look like $receiver.method($args..). Method calls in Rust
involve a fair bit of implicit magic: the receiver expression may be referenced and/or dereferenced
to get to the right type, and figuring out which methods are available requires trait solving.
Explaining how that works is out of scope for this guide (see [expr
#![allow(unused)] fn main() { let opt = Some(42); let x: &i32 = opt.as_ref().clone().unwrap(); // desugars to: let x: &i32 = Option::unwrap(<Option<&i32> as Clone>::clone(&Option::as_ref(&opt))); }
The <Type as Trait>::method(self, args..) syntax is called UFCS (Uniform Function Call Syntax)
[expropt got borrowed
into &opt in order to match the type required for Option::as_ref.
Aside postfix method calls, a number of operations can be overridden using traits. We desugar such overridden operations into the appropriate method call:
a + b -> Add::add(a, b)a += b -> AddAssign::add_assign(&mut a, b)a - b -> Sub::sub(a, b)-a -> Neg::neg(a)a[b] -> Index::index(&a, b)/IndexMut::index_mut(&mut a, b)f(args...) -> Fn::call/FnMut::call_mut/FnOnce::call_once(f, (args...))- etc
The non-overriden versions of these operations stay unchanged.
For example + on integers is built-in, but on integer references is defined by a trait:
#![allow(unused)] fn main() { let x = 1 + 2 + &3; // becomes let x = 1 + <i32 as Add<&i32>>::add(2, &3); }
Note that we don’t handle the * operator (overrideable with Deref/DerefMut) here, we’ll do it
in Deref/DerefMut Desugarings.
At the end of this step every method call and overridden operator use has been turned into a plain function call.