|
3 | 3 | /// In addition to being used for explicit dereferencing operations with the
|
4 | 4 | /// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
|
5 | 5 | /// by the compiler in many circumstances. This mechanism is called
|
6 |
| -/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used and |
| 6 | +/// ['`Deref` coercion'][coercion]. In mutable contexts, [`DerefMut`] is used and |
7 | 7 | /// mutable deref coercion similarly occurs.
|
8 | 8 | ///
|
9 |
| -/// Deref coercion is a powerful language feature and has far-reaching |
10 |
| -/// implications for every type implementing `Deref`: the compiler will often |
11 |
| -/// implicitly call `Deref::deref`, as described [below][more]. For this reason, |
12 |
| -/// `Deref` should not be implemented unless all of the implications of coercion |
13 |
| -/// are understood and desired. Implementing `Deref` is most commonly desirable |
14 |
| -/// when a type |
15 |
| -/// |
16 |
| -/// 1. should transparently behave like a contained value; and |
17 |
| -/// 2. does not have a rich set of methods in of itself, to avoid conflict or |
18 |
| -/// confusion with methods on the `Target` type. |
19 |
| -/// |
20 |
| -/// For example, [`Box<T>`][box] is perhaps the canonical example for `Deref`: |
21 |
| -/// a `Box<T>` value **is** a `T` value that is heap-allocated, so deref |
22 |
| -/// coercion intuitively makes `Box<T>` act like `T`. `Box<T>` |
23 |
| -/// also has very few methods (though several associated functions), so it is |
24 |
| -/// unlikely that users will find conflict with methods on their target type. |
25 |
| -/// [`RefCell<T>`][refcell] also contains a value of `T`, but while it could |
26 |
| -/// implement `DerefMut`, it does not since there is a rich API of methods to |
27 |
| -/// explicitly manage the owned value: allowing deref coercion in this case |
28 |
| -/// would hide the explicit management and likely cause confusion. |
29 |
| -/// |
30 |
| -/// Types that implement `Deref` and `DerefMut` are often called "smart |
| 9 | +/// **Warning:** Deref coercion is a powerful language feature which has |
| 10 | +/// far-reaching implications for every type that implements `Deref`. The |
| 11 | +/// compiler will silently insert calls to `Deref::deref`. For this reason, one |
| 12 | +/// should be careful about implementing `Deref` and only do so when deref |
| 13 | +/// coercion is desirable. See [below][implementing] for advice on when this is |
| 14 | +/// typeically desired or undesirable. |
| 15 | +/// |
| 16 | +/// Types that implement `Deref` or `DerefMut` are often called "smart |
31 | 17 | /// pointers" and the mechanism of deref coercion has been specifically designed
|
32 |
| -/// to facilitate the pointer-like behaviour that name suggests. Very often, the |
33 |
| -/// only purpose of a "smart pointer" type is to change the ownership semantics |
| 18 | +/// to facilitate the pointer-like behaviour that name suggests. Often, the |
| 19 | +/// purpose of a "smart pointer" type is to change the ownership semantics |
34 | 20 | /// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the
|
35 | 21 | /// storage semantics of a contained value (for example, [`Box`][box]).
|
36 | 22 | ///
|
37 |
| -/// If deref coercion is not desirable, the [`AsRef`] or [`Borrow`][borrow] |
38 |
| -/// traits are alternatives which should be preferred in most cases. |
39 |
| -/// |
40 |
| -/// # Fallibility |
41 |
| -/// |
42 |
| -/// **This trait's method should never fail**. Deref coercion means the compiler |
43 |
| -/// will often implicitly call `Deref::deref`. Failure during |
44 |
| -/// dereferencing can be extremely confusing when `Deref` is invoked implicitly. |
45 |
| -/// |
46 |
| -/// # More on `Deref` coercion |
| 23 | +/// # Deref coercion |
47 | 24 | ///
|
48 |
| -/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then: |
| 25 | +/// If `T` implements `Deref<Target = U>`, and `v` is a value of type `T`, then: |
49 | 26 | ///
|
50 |
| -/// * In immutable contexts, `*x` (where `T` is neither a reference nor a raw pointer) |
51 |
| -/// is equivalent to `*Deref::deref(&x)`. |
| 27 | +/// * In immutable contexts, `*v` (where `T` is neither a reference nor a raw |
| 28 | +/// pointer) is equivalent to `*Deref::deref(&x)`. |
52 | 29 | /// * Values of type `&T` are coerced to values of type `&U`
|
53 | 30 | /// * `T` implicitly implements all the methods of the type `U` which take the
|
54 | 31 | /// `&self` receiver.
|
55 | 32 | ///
|
56 | 33 | /// For more details, visit [the chapter in *The Rust Programming Language*][book]
|
57 | 34 | /// as well as the reference sections on [the dereference operator][ref-deref-op],
|
58 |
| -/// [method resolution] and [type coercions]. |
| 35 | +/// [method resolution], and [type coercions]. |
| 36 | +/// |
| 37 | +/// # When to implement `Deref` or `DerefMut` |
| 38 | +/// |
| 39 | +/// The same advice applies to both deref traits. In general, deref traits |
| 40 | +/// **should** be implemented if: |
| 41 | +/// |
| 42 | +/// 1. a value of the type transparently behaves like a value of the target |
| 43 | +/// type; |
| 44 | +/// 1. the implementation of the deref function is cheap; and |
| 45 | +/// 1. users of the type will not be surprised by any deref coercion behaviour. |
| 46 | +/// |
| 47 | +/// In general, deref traits **should not** be implemented if: |
| 48 | +/// |
| 49 | +/// 1. the deref implementations could fail unexpectedly; or |
| 50 | +/// 1. the type has methods that are likely to collide with methods on the |
| 51 | +/// target type; or |
| 52 | +/// 1. committing to deref coercion as part of the public API is not desirable. |
| 53 | +/// |
| 54 | +/// Note that there's a large difference between implementing deref traits |
| 55 | +/// generically over many target types, and doing so only for specific target |
| 56 | +/// types. |
| 57 | +/// |
| 58 | +/// Generic implementations, such as for [`Box<T>`][box] (which is generic over |
| 59 | +/// every type) should be careful to few methods, since the target type |
| 60 | +/// is unknown and therefore every method could collide with one on the target |
| 61 | +/// type, causing confusion for users. `Box<T>` has few methods (though |
| 62 | +/// several associated functions), partly for this reason. |
| 63 | +/// |
| 64 | +/// Specific implementations, such as for [`String`][string] (which only |
| 65 | +/// implements for `Target = str`) can have many methods, since avoiding |
| 66 | +/// collision is much easier. `String` and `str` both have many methods, and |
| 67 | +/// `String` additionally behaves as if it has every method of `str` because of |
| 68 | +/// deref coercion. |
| 69 | +/// |
| 70 | +/// Consider also that deref coericion means that deref traits are a much larger |
| 71 | +/// part of a type's public API than any other trait as it is implicitly called |
| 72 | +/// by the compiler. Therefore, it is advisable to consider whether this is |
| 73 | +/// something you are comfortable supporting as a public API. |
| 74 | +/// |
| 75 | +/// The [`AsRef`] and [`Borrow`][core::borrow::Borrow] traits have very similar |
| 76 | +/// signatures to `Deref`. It may be desirable to implement either or both of |
| 77 | +/// these, whether in addition to or rather than deref traits. See their |
| 78 | +/// documentation for details. |
| 79 | +/// |
| 80 | +/// # Fallibility |
| 81 | +/// |
| 82 | +/// **This trait's method should never unexpectedly fail**. Deref coercion means |
| 83 | +/// the compiler will often insert calls to `Deref::deref` implicitly. Failure |
| 84 | +/// during dereferencing can be extremely confusing when `Deref` is invoked |
| 85 | +/// implicitly. In the majority of uses it should be infallible, though it may |
| 86 | +/// be acceptable to panic if the type is misused through programmer error, for |
| 87 | +/// example. |
59 | 88 | ///
|
60 | 89 | /// [book]: ../../book/ch15-02-deref.html
|
61 |
| -/// [more]: #more-on-deref-coercion |
| 90 | +/// [coercion]: #deref-coercion |
| 91 | +/// [implementing]: #when-to-implement-deref-or-derefmut |
62 | 92 | /// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
|
63 | 93 | /// [method resolution]: ../../reference/expressions/method-call-expr.html
|
64 | 94 | /// [type coercions]: ../../reference/type-coercions.html
|
65 |
| -/// [box]: ../../std/boxed/struct.Box.html |
66 |
| -/// [refcell]: ../../std/cell/struct.RefCell.html |
67 |
| -/// [rc]: ../../std/rc/struct.Rc.html |
68 |
| -/// [cow]: ../../std/borrow/enum.Cow.html |
69 |
| -/// [borrow]: ../../std/borrow/trait.Borrow.html |
| 95 | +/// [box]: ../../alloc/boxed/struct.Box.html |
| 96 | +/// [string]: ../../alloc/string/struct.String.html |
| 97 | +/// [rc]: ../../alloc/rc/struct.Rc.html |
| 98 | +/// [cow]: ../../alloc/borrow/enum.Cow.html |
| 99 | +/// [borrow]: core::borrow::Borrow |
70 | 100 | ///
|
71 | 101 | /// # Examples
|
72 | 102 | ///
|
|
0 commit comments