Rust's Deref Trait: Smart Pointers Acting Like Data
The `Deref` trait lets a "smart pointer" type act like the data it contains, making wrappers transparent. It enables calling an inner type's methods directly on a wrapper, like using `&str` methods on a `String`. Its `deref()` method must never fail.
WHY IT EXISTS Rust uses wrapper types, or "smart pointers," to manage ownership and storage, like Box<T> or Rc<T>. Without a special mechanism, accessing the inner data T would require verbose syntax like my_box.inner.some_method(). The Deref trait was created to make these wrappers ergonomic, allowing them to behave like the data they hold.
THE MENTAL MODEL Think of Deref as a one-way lens. It lets a wrapper type, like String, provide a transparent "view" into its underlying data, str. The compiler automatically looks through this lens for you when you try to call a method, a mechanism called "Deref coercion." This makes the wrapper feel like the value it contains.
HOW IT WORKS To use it, you implement trait Deref for your type. This requires defining one method, deref(&self), which must return a reference to the inner data (&Self::Target). When the compiler sees you call a method on a reference to your wrapper (&MyWrapper) that only exists on the inner type (&InnerData), it silently inserts a call to .deref() to convert the types and make the call succeed.
WHEN TO USE IT Implement Deref when your type is a true smart pointer that transparently manages another value. The key is that the wrapper should behave just like the inner value in most contexts, and the deref() operation must be computationally cheap. This is for types that are fundamentally pointers-in-disguise.
WHEN NOT TO USE IT The biggest footgun is fallibility. The deref() method should never panic, because the compiler calls it implicitly in many places, and a hidden panic is extremely difficult to debug. Also, avoid implementing Deref if your wrapper type has methods that could clash with the inner type's methods; this is why Box<T> has almost no methods of its own. Finally, implementing Deref is a very strong public API commitment that you cannot easily take back.
ONE CANONICAL EXAMPLE The relationship between String and str is the classic case. String is an owned, heap-allocated buffer. It implements Deref<Target = str>. This allows you to call any &str method (like .len(), .lines(), or .trim()) directly on a String value, because the compiler automatically coerces &String into &str for you.
Read the original → doc.rust-lang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.