Rust
Deref
Learn automatic reference resolution with the Deref trait.
Deref
The Deref trait determines how a type behaves with the * operator. This is what lets smart pointers be used "like the value they hold":
use std::ops::Deref;
struct Sarici<T>(T);
impl<T> Deref for Sarici<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
let s = Sarici(String::from("Ece"));
println!("{}", s.len()); // 3: String's method
type Target is the trait's associated type: it says which type you get when dereferencing.
Chained conversion
Deref coercion works in a chain and has no runtime cost:
fn selam(ad: &str) -> String {
format!("Merhaba {ad}")
}
let s = Sarici(String::from("Ece"));
println!("{}", selam(&s)); // &Sarici<String> → &String → &str
Implement Deref only for smart-pointer-like types; adding it to an ordinary struct creates "hidden" behaviour and hurts readability. The mutable version is DerefMut.
Exercise Wrapper
Implement Deref for the Sarici<T> type above and write fn selam(ad: &str) -> String. For Sarici(String::from("Ece")), print the result of selam(&s) and the value of s.len() separated by a space.
Show example solution
use std::ops::Deref;
struct Sarici<T>(T);
impl<T> Deref for Sarici<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
fn selam(ad: &str) -> String {
format!("Merhaba {ad}")
}
fn main() {
let s = Sarici(String::from("Ece"));
println!("{} {}", selam(&s), s.len());
}
Test yourself
-
What does deref coercion do?
- Only works for Box
- Automatically converts references like &Sarici<String> → &String → &str
- Copies the value
- Moves ownership
Show answer
Automatically converts references like &Sarici<String> → &String → &str — The compiler adds the deref chain until it reaches the expected type; that's why a &String can be passed where &str is expected.
-
Associated type
impl<T> Deref for Sarici<T> {
type ____ = T;
fn deref(&self) -> &T {
&self.0
}
}
Show answer
impl<T> Deref for Sarici<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
-
Type and Target
- Box<T>
- T
- String
- str
- Vec<T>
- [T]
- Rc<T>
- T (shared)
Next lesson: Summary - Smart pointers