-
Notifications
You must be signed in to change notification settings - Fork 13.3k
TRPL: Borrow and AsRef #24996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TRPL: Borrow and AsRef #24996
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
% Borrow and AsRef | ||
|
||
The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but | ||
different. Here’s a quick refresher on what these two traits mean. | ||
|
||
[borrow]: ../std/borrow/trait.Borrow.html | ||
[asref]: ../std/convert/trait.AsRef.html | ||
|
||
# Borrow | ||
|
||
The `Borrow` trait is used when you’re writing a datastructure, and you want to | ||
use either an owned or borrowed type as synonymous for some purpose. | ||
|
||
For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`: | ||
|
||
```rust,ignore | ||
fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> | ||
where K: Borrow<Q>, | ||
Q: Hash + Eq | ||
``` | ||
|
||
[hashmap]: ../std/collections/struct.HashMap.html | ||
[get]: ../std/collections/struct.HashMap.html#method.get | ||
|
||
This signature is pretty complicated. The `K` parameter is what we’re interested | ||
in here. It refers to a parameter of the `HashMap` itself: | ||
|
||
```rust,ignore | ||
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: | ||
|
||
```rust | ||
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. Slices are an area where this is especially true: 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. | ||
|
||
# AsRef | ||
|
||
The `AsRef` trait is a conversion trait. It’s used for converting some value to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be clear, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
a reference in generic code. Like this: | ||
|
||
```rust | ||
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 datastructure 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you could include the output here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍