Skip to main content
The . (dot) operator in Rust is a postfix expression operator used for struct field access, tuple indexing, and method invocation. Its defining characteristic is that it performs implicit auto-referencing, auto-dereferencing, and unsized coercion during method resolution, allowing the compiler to automatically align the receiver’s type with the method’s signature.

Field Access and Tuple Indexing

When used for data access, the dot operator evaluates the operand to the left and accesses the specified named field or numeric tuple index. If the receiver is a reference (e.g., &T, &mut T, or a chain of references like &&T), the dot operator implicitly dereferences the pointer to access the underlying data. You do not need to manually write (*receiver).field.

Method Resolution Algorithm

When the dot operator is used for method invocation (receiver.method()), the Rust compiler executes a specific algorithm to find a matching method implementation. It systematically alters the type of the receiver (denoted as T) until it matches the self parameter of a method. The compiler attempts the following transformations in order:
  1. By Value: It checks if there is a method that accepts T directly (i.e., self).
  2. Auto-Referencing: It checks if there is a method that accepts &T or &mut T (i.e., &self or &mut self). The compiler implicitly borrows the receiver.
  3. Auto-Dereferencing: If T is a built-in reference type (e.g., &U or &mut U), the compiler strips the reference to yield U. Alternatively, if T implements the Deref (or DerefMut) trait, the compiler dereferences T to its target type U (i.e., *T). It then restarts the resolution process at Step 1 using U. This step repeats recursively, which is how methods on smart pointers like Box<T>, Rc<T>, or String transparently call methods on their underlying types.
  4. Unsized Coercion: If the type cannot be resolved through referencing or dereferencing, the compiler attempts to coerce the type into an unsized type. The most common coercion is converting an array [T; N] into a slice [T].

Operator Precedence

The . operator has a very high precedence level in Rust’s expression syntax, sitting just below the path operator (::). It shares its precedence tier with the method call operator, field expression, array indexing ([]), and the try operator (?). Because of this high precedence, expressions like &instance.field are evaluated as &(instance.field), not (&instance).field.
Tired of Poor Rust Skills? Fix That With Deep Grasping!Learn More