Rustコトハジメ

プログラミング言語Rustに関する情報をお届けします。

Understand the reference resolution rule in Rust

There is a lot of implicit type conversions in Rust. Some of them are

  • auto-referencing: Rust compiler add & or &mut automatically to the &self or &mut self in method call.
  • auto-dereferencing: Rust compiler dereferences type by adding * until the type matches the wanted.

and you might be confused which applies to which situation and what is the possible combination.

So in this article we will roughly understand the core algorithm of the reference resolution explained in the stackoverflow thread:

stackoverflow.com

f:id:akiradeveloper529:20190307141357j:plain

The interesting thing to me is that the outer loop for the dereferencing because we programmers think in the reverse direction.

impl ops::Deref for String {
    type Target = str;

    #[inline]
    fn deref(&self) -> &str {
        unsafe { str::from_utf8_unchecked(&self.vec) }
    }
}

For example when we call trim method (whose 1st argument is &str) to a String object we think in this order

  1. String turns into &String (auto-referencing)
  2. &String turns into &str (auto-dereferencing)

but the algorithm actually thinks in the reverse order:

  1. U=String is rejected. Try U = *String and we get *deref(&String) = *&str = str (*x on non-pointer types is equivalent to *Deref::deref(&x) std::ops::Deref - Rust)
  2. Reach &str by auto-referencing

to match the wanted type &str.