Essential Standard Traits

Deref and DerefMut

The Deref and DerefMut traits in std::ops overload the unary dereference operator (*value) for smart pointers and owning wrapper types, and power the compiler's implicit deref coercion mechanism.

Trait Definitions

pub trait Deref {
    type Target: ?Sized;

    fn deref(&self) -> &Self::Target;
}

pub trait DerefMut: Deref {
    fn deref_mut(&mut self) -> &mut Self::Target;
}

When *x is evaluated on an immutable smart pointer, the compiler rewrites it to *(Deref::deref(&x)). When *x is evaluated in a mutable context, the compiler rewrites it to *(DerefMut::deref_mut(&mut x)).

Standard Library Deref Implementations

Smart Pointer / Owner Deref::Target Effect of Deref Coercion
Box<T> T &Box<T> coerces to &T; &mut Box<T> coerces to &mut T
Rc<T> / Arc<T> T &Rc<T> and &Arc<T> coerce to &T (no DerefMut because ownership is shared)
String str &String coerces to &str, exposing all str methods on String
Vec<T> [T] &Vec<T> coerces to &[T], exposing all slice methods on Vec<T>
MutexGuard<'_, T> T Guard acts as a smart pointer to the protected value T

Implementing Deref and DerefMut on a Smart Pointer

use std::ops::{Deref, DerefMut};

struct TrackedBox<T> {
    value: T,
    mutations: usize,
}

impl<T> TrackedBox<T> {
    fn new(value: T) -> Self {
        Self {
            value,
            mutations: 0,
        }
    }
}

impl<T> Deref for TrackedBox<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.value
    }
}

impl<T> DerefMut for TrackedBox<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.mutations += 1;
        &mut self.value
    }
}

fn greet(name: &str) {
    println!("Hello, {name}!");
}

fn main() {
    let mut tracked = TrackedBox::new(String::from("Rust"));
    tracked.push_str(" 2024"); // Uses DerefMut<Target = String>

    // Deref coercion chain: &TrackedBox<String> -> &String -> &str
    greet(&tracked);
    println!("Mutations recorded: {}", tracked.mutations);
}
Hello, Rust 2024!
Mutations recorded: 1

Implicit Deref Coercion Rules

When passing a reference or calling a method via the . operator, the compiler automatically applies Deref::deref or DerefMut::deref_mut as many times as needed to match the expected type:

  • &T to &U when T: Deref<Target = U>
  • &mut T to &mut U when T: DerefMut<Target = U>
  • &mut T to &U when T: Deref<Target = U> (mutable reference weakens to shared reference; the reverse is never permitted)

Only implement Deref for smart pointer or transparent wrapper types—never to simulate class inheritance between unrelated domain structs.