In Rust, it is common to provide different representations of a type for different use cases. For instance, storage location and management for a value can be specifically chosen as appropriate for a particular use via pointer types such as Box<T> or Rc<T>. Beyond these generic wrappers that can be used with any type, some types provide optional facets providing potentially costly functionality. An example for such a type is String which adds the ability to extend a string to the basic str. This requires keeping additional information unnecessary for a simple, immutable string.
Types express that they can be borrowed as some type T by implementing Borrow, providing a reference to a T in the trait’s borrow method. A type is free to borrow as several different types. If it wishes to mutably borrow as the type – allowing the underlying data to be modified, it can additionally implement BorrowMut.
NOTE: If generic code merely needs to work for all types that can provide a reference to related type T, it is often better to use AsRef as more types can safely implement it.
HashMap's get method is an example usage of this trait:
use std::borrow::Borrow;
use std::hash::Hash;
pub struct HashMap<K, V> {
// fields omitted
}
impl<K, V> HashMap<K, V> {
pub fn insert(&self, key: K, value: V) -> Option<V>
where K: Hash + Eq
{
// ...
}
pub fn get<Q>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized
{
// ...
}
}