Borrow and AsRef - The Rust Programming Language

# Borrow and AsRef

The `Borrow` and `AsRef` traits are very similar, but different. Here’s a quick refresher on what these two traits mean.

# Borrow

The `Borrow` trait is used when you’re writing a data structure, and you want to use either an owned or borrowed type as synonymous for some purpose.

For example, `HashMap` has a `get` method which uses `Borrow`:

    fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
        where K: Borrow<Q>,
              Q: Hash + Eq

This signature is pretty complicated. The `K` parameter is what we’re interested in here. It refers to a parameter of the `HashMap` itself:

    struct HashMap<K, V, S = RandomState> {

The `K` parameter is the type of key the `HashMap` uses. So, looking at the signature of `get()` again, we can use `get()` when the key implements `Borrow<Q>`. That way, we can make a `HashMap` which uses `String` keys, but use `&str`s when we’re searching:

    # #![allow(unused_variables)]
    #fn main() {
    use std::collections::HashMap;

    let mut map = HashMap::new();
    map.insert("Foo".to_string(), 42);

    assert_eq!(map.get("Foo"), Some(&42));
    #}

This is because the standard library has `impl Borrow<str> for String`.

For most types, when you want to take an owned or borrowed type, a `&T` is enough. But one area where `Borrow` is effective is when there’s more than one kind of borrowed value. This is especially true of references and slices: you can have both an `&T` or a `&mut T`. If we wanted to accept both of these types, `Borrow` is up for it:

    # #![allow(unused_variables)]
    #fn main() {
    use std::borrow::Borrow;
    use std::fmt::Display;

    fn foo<T: Borrow<i32> + Display>(a: T) {
        println!("a is borrowed: {}", a);
    }

    let mut i = 5;

    foo(&i);
    foo(&mut i);
    #}

This will print out `a is borrowed: 5` twice.

# AsRef

The `AsRef` trait is a conversion trait. It’s used for converting some value to a reference in generic code. Like this:

    # #![allow(unused_variables)]
    #fn main() {
    let s = "Hello".to_string();

    fn foo<T: AsRef<str>>(s: T) {
        let slice = s.as_ref();
    }
    #}

# Which should I use?

We can see how they’re kind of the same: they both deal with owned and borrowed versions of some type. However, they’re a bit different.

Choose `Borrow` when you want to abstract over different kinds of borrowing, or when you’re building a data structure that treats owned and borrowed values in equivalent ways, such as hashing and comparison.

Choose `AsRef` when you want to convert something to a reference directly, and you’re writing generic code.