I try to understand the borrow mechanism and references in Rust, and for this reason I created the following small example:
extern crate core;
use core::fmt::Debug;
#[derive(Copy, Clone)]
pub struct Element(pub (crate) [u8; 5]);
impl Debug for Element {
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        write!(f, "Element({:?})", &self.0[..])
    }
}
impl Element {
    fn one() -> Element {
        Element([1, 1, 1, 1, 1])
    }
    fn double(&self) -> Element {
        let mut result = *self;
        for i in 0..5 { result.0[i] = 2*result.0[i]; }
        result
    }
    fn mut_double(&mut self) -> Element {
      for i in 0..5 { self.0[i] = 2*self.0[i]; }
      *self
    }
}
fn main() {
  let mut a = Element::one();
  println!("a = {:?}", a); // a = Element([1, 1, 1, 1, 1])
  a = a.double();
  println!("a = {:?}", a); // a = Element([2, 2, 2, 2, 2])
  a = (&a).double();
  println!("a = {:?}", a); // a = Element([4, 4, 4, 4, 4])
  a = a.mut_double();
  println!("a = {:?}", a); // a = Element([8, 8, 8, 8, 8])
  a = (&mut a).mut_double();
  println!("a = {:?}", a); // a = Element([16, 16, 16, 16, 16])
}
So, the above code works, but my confusion comes when calling the double method. As you can see it is defined as fn double(&self) -> Element, so it basically takes an immutable reference. Now in the main, I create a new Element variable called a, and then call double method on it twice. First time I just do a.double(), second time (&a).double(). Both of them seem to work correctly, but I do not understand why the first call a.double() is a valid and compiler doesn't complain about it. Since a is of type Element, not of type &Element, and clearly the double method asks for &Element, so about a reference. Same thing also happens with the mut_double method. Why do I not have to specify (&a) or (&mut a) when calling the double and mut_double methods, respectively? What is happening under the hood with Rust?
 
    