Skip to main content

Deref Coercion in Rust

ยท 2 min read

Deref coercion is Rust automatically converting one reference type to another when it makes sense to do so.

The simplest example: &String automatically becomes &str where needed.

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

let s = String::from("world");
greet(&s); // &String coerces to &str

This works because String implements Deref<Target = str>. The compiler sees you have a &String, the function wants &str, and it knows how to convert.

This happens with smart pointers too. Box<T> derefs to T, so you can call methods on T directly:

let boxed = Box::new(vec![1, 2, 3]);
println!("{}", boxed.len()); // calls Vec::len through the Box

The pattern extends: Vec<T> derefs to [T], so you get slice methods on vectors. Rc<T> and Arc<T> deref to T.

The compiler will chain these coercions. &Box<String> can become &String can become &str, all automatically.

It's convenient, but can be surprising if you're not expecting it. When a method call "just works" on a wrapper type, deref coercion is usually why.

One thing to watch out for: don't use Deref to fake inheritance. It's tempting to wrap a type and implement Deref to get "free" method forwarding, but the implicit behavior can confuse readers. Use it for smart pointer-like types, not as a substitute for composition.