C.W.K.
Stream
Lesson 02 of 05 · published

Deref & Drop

~10 min · smart-pointers, deref, drop, coercion

Level 0Rust Curious
0 XP0/80 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete

Why can you call String methods on a Box<String>, or pass &String where &str is wanted? The answer is the Deref trait — the mechanism that lets smart pointers feel transparent.

Deref: act like what you point to

Implementing Deref lets *pointer return a reference to the inner value, and — more importantly — enables deref coercion: the compiler automatically converts &Box<T> to &T, &String to &str, and so on, wherever a method or function expects the inner type. That's why a Box<String> 'just works' as a String.

Deref coercion in practice

You've relied on this since the Borrowing track without naming it: passing &my_string to a &str parameter works because String derefs to str. The compiler chains deref coercions as needed, so a &Box<String> can reach a &str parameter through two steps, invisibly.

Deref makes smart pointers transparent. Because Box, Rc, and friends implement Deref, you call the inner value's methods directly through them. The smart pointer adds its capability (heap storage, ref counting) without making you constantly unwrap to use the value.

Drop, the companion

You met Drop in the Ownership track — the cleanup that runs at end of scope. Smart pointers lean on it: when a Box drops, it frees its heap allocation; when an Rc drops, it decrements the count and frees only at zero. Deref and Drop together are what make a smart pointer behave like a value while managing a resource behind the scenes.

Code

Implementing Deref to get transparent access·rust
use std::ops::Deref;

struct MyBox<T>(T);

impl<T> MyBox<T> {
    fn new(x: T) -> MyBox<T> { MyBox(x) }
}
impl<T> Deref for MyBox<T> {
    type Target = T;
    fn deref(&self) -> &T { &self.0 } // *my_box now reaches the inner value
}

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

fn main() {
    let b = MyBox::new(String::from("Ferris"));
    // deref coercion: &MyBox<String> -> &String -> &str, automatically
    hello(&b);
    println!("{}", *b); // explicit deref
}

External links

Exercise

Implement a MyBox<T> tuple struct with Deref. Write a function taking &str and call it with &MyBox<String> — confirm deref coercion chains MyBox<String> -> String -> str for you. Then remove the Deref impl and watch the call stop compiling. What did Deref buy you?
Hint
Without Deref, &MyBox<String> is just an opaque wrapper — no automatic conversion to &str. Implementing Deref is what lets the compiler see through the wrapper to the value inside.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.