The Borrow and AsRef traits are very similar, but different. Here’s a quick refresher on what these two traits mean.
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 &strs when we’re searching:
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:
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.
The AsRef trait is a conversion trait. It’s used for converting some value to a reference in generic code. Like this:
let s = "Hello".to_string();
fn foo<T: AsRef<str>>(s: T) {
let slice = s.as_ref();
} 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.
© 2010 The Rust Project Developers
Licensed under the Apache License, Version 2.0 or the MIT license, at your option.
https://doc.rust-lang.org/book/borrow-and-asref.html