Deref coercions - The Rust Programming Language

You are reading an outdated edition of TRPL. For more, go here.

# `Deref` coercions

The standard library provides a special trait, `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);
    }

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

    # #![allow(unused_variables)]
    #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);
    #}

Using an ampersand in front of a value takes a reference to it. So `owned` is a `String`, `&owned` is an `&String`, and since `impl Deref<Target=str> for String`, `&String` will deref to `&str`, which `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>` type implements `Deref<Target=T>`, so this works:

    # #![allow(unused_variables)]
    #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);
    #}

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

Another very common implementation provided by the standard library is:

    # #![allow(unused_variables)]
    #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);
    #}

Vectors can `Deref` to a slice.

## Deref and method calls

`Deref` will also kick in when calling a method. Consider the following example.

    # #![allow(unused_variables)]
    #fn main() {
    struct Foo;

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

    let f = &&Foo;

    f.foo();
    #}

Even though `f` is a `&&Foo` and `foo` takes `&self`, this works. That’s because these things are the same:

    f.foo();
    (&f).foo();
    (&&f).foo();
    (&&&&&&&&f).foo();

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