forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of rust-lang#24996 - steveklabnik:gh24163, r=aturon
These two traits are commonly confused. As such, explain the difference. Fixes rust-lang#24163 r? @aturon
- Loading branch information
Showing
4 changed files
with
104 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters