01.15.2022 - Rust/Deref and DerefMut

All posts

Posted On 01.15.2022

The traits std::ops::Deref and std::ops::DerefMut are used for explicit dereference operations (immutable or mutable), like:

// immutable dereference
println!("{}", *a);
 
// mutable dereference
*a = <something>;

If a type T implements Deref<Target=U> or DerefMut<Target=U> like this:

impl<T> Deref for Something<T> {
  type Target = T;
 
  fn deref(&self) -> &Self::Target {
    &self.value
  }
}
 
impl<T> DerefMut for Something<T> {
  type Target = T;
 
  fn deref_mut(&mut self) -> &mut Self::Target {
    &mut self.value
  }
}
  • Any usage of *a in immutable contexts are equivalent to *Deref::deref(&a), and *DerefMut::deref_mut(&mut a) in mutable contexts.

  • Any values of type &T will be coerced to values of type &U, and values of type &mut T will be coerced to values of type &mut U. Mutable references &mut T can also be coerced to immutable references &U, not the other way around, immutable references &T cannot be coerced to mutable references &mut U.

    For example, because type String implemented Deref<U=&str>, we can pass a reference &String to any function that takes a &str:

    fn hello(name: &str) {
      ...
    }
     
    let name: String = String::from("Huy");
    hello(&name); // this works
    
  • Type T will implicitly implement all the immutable (for Deref) and mutable (for DerefMut) methods of type U.

    For example, when creating a wrapped type using tuple struct (see previous post), you cannot access any methods of the inner type from the wrapped type:

    struct List(Vec<i32>);
     
    let list = List(vec![1, 2, 3]);
    println!("{}", list.last());
     
    // 1    | struct List(Vec<i32>);
    //      | ----------------------
    //      | |
    //      | method `last` not found for this
    //      | doesn't satisfy `List: Iterator`
    // ...
    // 5    |   println!("{}", list.last());
    //
    

    If you implement Deref or DerefMut for the wrapped type, it will implicitly implement all the immutable or mutable methods from the inner type:

    impl Deref for List {
      type Target = Vec<i32>;
      
      fn deref(&self) -> &Self::Target {
        &self.0
      }
    }
     
    println!("{}", list.first());
    // Output: 1
    

You can read more about Deref and DerefMut in The Rust Programming Language Book, or in the documentation.