`Deref` coercions

The standard library provides a special trait, Deref`Deref`. It’s normally used to overload *`*`, the dereference operator:

use std::ops::Deref; struct DerefExample<T> { value: T, } impl<T> Deref for DerefExample<T> { type Target = T; fn deref(&self) -> &T { &self.value } } fn main() { let x = DerefExample { value: 'a' }; assert_eq!('a', *x); }
use std::ops::Deref;

struct DerefExample<T> {
    value: T,
}

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

    fn deref(&self) -> &T {
        &self.value
    }
}

fn main() {
    let x = DerefExample { value: 'a' };
    assert_eq!('a', *x);
}

This is useful for writing custom pointer types. However, there’s a language feature related to Deref`Deref: ‘deref coercions’. Here’s the rule: If you have a type`: ‘deref coercions’. Here’s the rule: If you have a type U`U, and it implements`, and it implements Deref<Target=T>`Deref, values of`, values of &U`&Uwill automatically coerce to a` will automatically coerce to a &T`&T`. Here’s an example:

fn main() { fn foo(s: &str) { // borrow a string for a second } // String implements Deref<Target=str> let owned = "Hello".to_string(); // therefore, this works: foo(&owned); }
fn foo(s: &str) {
    // borrow a string for a second
}

// String implements Deref<Target=str>
let owned = "Hello".to_string();

// therefore, this works:
foo(&owned);

Using an ampersand in front of a value takes a reference to it. So owned`ownedis a` is a String`String,`, &owned`&ownedis an` is an &String`&String, and since`, and since impl Deref<Target=str> for String`impl Deref for String,`, &String`&Stringwill deref to` will deref to &str`&str, which`, which foo()`foo()` takes.

That’s it. This rule is one of the only places in which Rust does an automatic conversion for you, but it adds a lot of flexibility. For example, the Rc<T>`Rctype implements` type implements Deref<Target=T>`Deref`, so this works:

fn main() { use std::rc::Rc; fn foo(s: &str) { // borrow a string for a second } // String implements Deref<Target=str> let owned = "Hello".to_string(); let counted = Rc::new(owned); // therefore, this works: foo(&counted); }
use std::rc::Rc;

fn foo(s: &str) {
    // borrow a string for a second
}

// String implements Deref<Target=str>
let owned = "Hello".to_string();
let counted = Rc::new(owned);

// therefore, this works:
foo(&counted);

All we’ve done is wrap our String`Stringin an` in an Rc<T>`Rc. But we can now pass the`. But we can now pass the Rc<String>`Rcaround anywhere we’d have a` around anywhere we’d have a String`String. The signature of`. The signature of foo`foodidn’t change, but works just as well with either type. This example has two conversions:` didn’t change, but works just as well with either type. This example has two conversions: Rc<String>`Rcto` to String`Stringand then` and then String`Stringto` to &str`&str`. Rust will do this as many times as possible until the types match.

Another very common implementation provided by the standard library is:

fn main() { fn foo(s: &[i32]) { // borrow a slice for a second } // Vec<T> implements Deref<Target=[T]> let owned = vec![1, 2, 3]; foo(&owned); }
fn foo(s: &[i32]) {
    // borrow a slice for a second
}

// Vec<T> implements Deref<Target=[T]>
let owned = vec![1, 2, 3];

foo(&owned);

Vectors can Deref`Deref` to a slice.

Deref and method calls

Deref`Deref` will also kick in when calling a method. In other words, these are the same two things in Rust:

fn main() { struct Foo; impl Foo { fn foo(&self) { println!("Foo"); } } let f = Foo; f.foo(); }
struct Foo;

impl Foo {
    fn foo(&self) { println!("Foo"); }
}

let f = Foo;

f.foo();

Even though f`fisn’t a reference, and` isn’t a reference, and foo`footakes` takes &self`&self`, this works. That’s because these things are the same:

fn main() { f.foo(); (&f).foo(); (&&f).foo(); (&&&&&&&&f).foo(); }
f.foo();
(&f).foo();
(&&f).foo();
(&&&&&&&&f).foo();

A value of type &&&&&&&&&&&&&&&&Foo`&&&&&&&&&&&&&&&&Foocan still have methods defined on` can still have methods defined on Foo`Foocalled, because the compiler will insert as many * operations as necessary to get it right. And since it’s inserting` called, because the compiler will insert as many * operations as necessary to get it right. And since it’s inserting *`*s, that uses`s, that uses Deref`Deref`.