Skip to content

Commit c7bc7d4

Browse files
authored
Unrolled build for rust-lang#110340
Rollup merge of rust-lang#110340 - jmaargh:jmaargh/deref-docs, r=Mark-Simulacrum Deref docs: expand and remove "smart pointer" qualifier **Ready for review** ~~This is an unpolished draft to be sanity-checked~~ Fixes rust-lang#91004 ~~Comments on substance and content of this are welcome. This is deliberately unpolished until ready to review so please try to stay focused on the big-picture.~~ ~~Once this has been sanity checked, I will similarly update `DerefMut` and polish for review.~~
2 parents a42d94e + 7a2f83f commit c7bc7d4

File tree

2 files changed

+125
-41
lines changed

2 files changed

+125
-41
lines changed

library/core/src/convert/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ pub const fn identity<T>(x: T) -> T {
138138
///
139139
/// [dereferenceable types]: core::ops::Deref
140140
/// [pointed-to value]: core::ops::Deref::Target
141-
/// ['`Deref` coercion']: core::ops::Deref#more-on-deref-coercion
141+
/// ['`Deref` coercion']: core::ops::Deref#deref-coercion
142142
///
143143
/// ```
144144
/// let x = Box::new(5i32);
@@ -244,7 +244,7 @@ pub trait AsRef<T: ?Sized> {
244244
///
245245
/// [mutably dereferenceable types]: core::ops::DerefMut
246246
/// [pointed-to value]: core::ops::Deref::Target
247-
/// ['`Deref` coercion']: core::ops::DerefMut#more-on-deref-coercion
247+
/// ['`Deref` coercion']: core::ops::DerefMut#mutable-deref-coercion
248248
///
249249
/// ```
250250
/// let mut x = Box::new(5i32);

library/core/src/ops/deref.rs

+123-39
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,107 @@
33
/// In addition to being used for explicit dereferencing operations with the
44
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
55
/// by the compiler in many circumstances. This mechanism is called
6-
/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
6+
/// ["`Deref` coercion"][coercion]. In mutable contexts, [`DerefMut`] is used and
7+
/// mutable deref coercion similarly occurs.
78
///
8-
/// Implementing `Deref` for smart pointers makes accessing the data behind them
9-
/// convenient, which is why they implement `Deref`. On the other hand, the
10-
/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
11-
/// accommodate smart pointers. Because of this, **`Deref` should only be
12-
/// implemented for smart pointers** to avoid confusion.
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+
/// typically desirable or undesirable.
1315
///
14-
/// For similar reasons, **this trait should never fail**. Failure during
15-
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
16+
/// Types that implement `Deref` or `DerefMut` are often called "smart
17+
/// pointers" and the mechanism of deref coercion has been specifically designed
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
20+
/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the
21+
/// storage semantics of a contained value (for example, [`Box`][box]).
1622
///
17-
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
18-
/// specified, but users of the trait must ensure that such logic errors do *not* result in
19-
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this
20-
/// method.
23+
/// # Deref coercion
2124
///
22-
/// # More on `Deref` coercion
25+
/// If `T` implements `Deref<Target = U>`, and `v` is a value of type `T`, then:
2326
///
24-
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
25-
///
26-
/// * In immutable contexts, `*x` (where `T` is neither a reference nor a raw pointer)
27-
/// 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(&v)`.
2829
/// * Values of type `&T` are coerced to values of type `&U`
29-
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
30+
/// * `T` implicitly implements all the methods of the type `U` which take the
31+
/// `&self` receiver.
3032
///
3133
/// For more details, visit [the chapter in *The Rust Programming Language*][book]
3234
/// as well as the reference sections on [the dereference operator][ref-deref-op],
33-
/// [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 and dereferences to `T`) should be careful to provide few or no
60+
/// methods, since the target type is unknown and therefore every method could
61+
/// collide with one on the target type, causing confusion for users.
62+
/// `impl<T> Box<T>` has no methods (though several associated functions),
63+
/// partly for this reason.
64+
///
65+
/// Specific implementations, such as for [`String`][string] (whose `Deref`
66+
/// implementation has `Target = str`) can have many methods, since avoiding
67+
/// collision is much easier. `String` and `str` both have many methods, and
68+
/// `String` additionally behaves as if it has every method of `str` because of
69+
/// deref coercion. The implementing type may also be generic while the
70+
/// implementation is still specific in this sense; for example, [`Vec<T>`][vec]
71+
/// dereferences to `[T]`, so methods of `T` are not applicable.
72+
///
73+
/// Consider also that deref coericion means that deref traits are a much larger
74+
/// part of a type's public API than any other trait as it is implicitly called
75+
/// by the compiler. Therefore, it is advisable to consider whether this is
76+
/// something you are comfortable supporting as a public API.
77+
///
78+
/// The [`AsRef`] and [`Borrow`][core::borrow::Borrow] traits have very similar
79+
/// signatures to `Deref`. It may be desirable to implement either or both of
80+
/// these, whether in addition to or rather than deref traits. See their
81+
/// documentation for details.
82+
///
83+
/// # Fallibility
84+
///
85+
/// **This trait's method should never unexpectedly fail**. Deref coercion means
86+
/// the compiler will often insert calls to `Deref::deref` implicitly. Failure
87+
/// during dereferencing can be extremely confusing when `Deref` is invoked
88+
/// implicitly. In the majority of uses it should be infallible, though it may
89+
/// be acceptable to panic if the type is misused through programmer error, for
90+
/// example.
91+
///
92+
/// However, infallibility is not enforced and therefore not guaranteed.
93+
/// As such, `unsafe` code should not rely on infallibility in general for
94+
/// soundness.
3495
///
3596
/// [book]: ../../book/ch15-02-deref.html
36-
/// [more]: #more-on-deref-coercion
97+
/// [coercion]: #deref-coercion
98+
/// [implementing]: #when-to-implement-deref-or-derefmut
3799
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
38100
/// [method resolution]: ../../reference/expressions/method-call-expr.html
39101
/// [type coercions]: ../../reference/type-coercions.html
102+
/// [box]: ../../alloc/boxed/struct.Box.html
103+
/// [string]: ../../alloc/string/struct.String.html
104+
/// [vec]: ../../alloc/vec/struct.Vec.html
105+
/// [rc]: ../../alloc/rc/struct.Rc.html
106+
/// [cow]: ../../alloc/borrow/enum.Cow.html
40107
///
41108
/// # Examples
42109
///
@@ -107,42 +174,59 @@ impl<T: ?Sized> Deref for &mut T {
107174
/// In addition to being used for explicit dereferencing operations with the
108175
/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
109176
/// by the compiler in many circumstances. This mechanism is called
110-
/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
111-
///
112-
/// Implementing `DerefMut` for smart pointers makes mutating the data behind
113-
/// them convenient, which is why they implement `DerefMut`. On the other hand,
114-
/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
115-
/// accommodate smart pointers. Because of this, **`DerefMut` should only be
116-
/// implemented for smart pointers** to avoid confusion.
177+
/// ["mutable deref coercion"][coercion]. In immutable contexts, [`Deref`] is used.
117178
///
118-
/// For similar reasons, **this trait should never fail**. Failure during
119-
/// dereferencing can be extremely confusing when `DerefMut` is invoked
120-
/// implicitly.
179+
/// **Warning:** Deref coercion is a powerful language feature which has
180+
/// far-reaching implications for every type that implements `DerefMut`. The
181+
/// compiler will silently insert calls to `DerefMut::deref_mut`. For this
182+
/// reason, one should be careful about implementing `DerefMut` and only do so
183+
/// when mutable deref coercion is desirable. See [the `Deref` docs][implementing]
184+
/// for advice on when this is typically desirable or undesirable.
121185
///
122-
/// Violating these requirements is a logic error. The behavior resulting from a logic error is not
123-
/// specified, but users of the trait must ensure that such logic errors do *not* result in
124-
/// undefined behavior. This means that `unsafe` code **must not** rely on the correctness of this
125-
/// method.
186+
/// Types that implement `DerefMut` or `Deref` are often called "smart
187+
/// pointers" and the mechanism of deref coercion has been specifically designed
188+
/// to facilitate the pointer-like behaviour that name suggests. Often, the
189+
/// purpose of a "smart pointer" type is to change the ownership semantics
190+
/// of a contained value (for example, [`Rc`][rc] or [`Cow`][cow]) or the
191+
/// storage semantics of a contained value (for example, [`Box`][box]).
126192
///
127-
/// # More on `Deref` coercion
193+
/// # Mutable deref coercion
128194
///
129-
/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
195+
/// If `T` implements `DerefMut<Target = U>`, and `v` is a value of type `T`,
130196
/// then:
131197
///
132-
/// * In mutable contexts, `*x` (where `T` is neither a reference nor a raw pointer)
133-
/// is equivalent to `*DerefMut::deref_mut(&mut x)`.
198+
/// * In mutable contexts, `*v` (where `T` is neither a reference nor a raw pointer)
199+
/// is equivalent to `*DerefMut::deref_mut(&mut v)`.
134200
/// * Values of type `&mut T` are coerced to values of type `&mut U`
135201
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
136202
///
137203
/// For more details, visit [the chapter in *The Rust Programming Language*][book]
138204
/// as well as the reference sections on [the dereference operator][ref-deref-op],
139205
/// [method resolution] and [type coercions].
140206
///
207+
/// # Fallibility
208+
///
209+
/// **This trait's method should never unexpectedly fail**. Deref coercion means
210+
/// the compiler will often insert calls to `DerefMut::deref_mut` implicitly.
211+
/// Failure during dereferencing can be extremely confusing when `DerefMut` is
212+
/// invoked implicitly. In the majority of uses it should be infallible, though
213+
/// it may be acceptable to panic if the type is misused through programmer
214+
/// error, for example.
215+
///
216+
/// However, infallibility is not enforced and therefore not guaranteed.
217+
/// As such, `unsafe` code should not rely on infallibility in general for
218+
/// soundness.
219+
///
141220
/// [book]: ../../book/ch15-02-deref.html
142-
/// [more]: #more-on-deref-coercion
221+
/// [coercion]: #mutable-deref-coercion
222+
/// [implementing]: Deref#when-to-implement-deref-or-derefmut
143223
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
144224
/// [method resolution]: ../../reference/expressions/method-call-expr.html
145225
/// [type coercions]: ../../reference/type-coercions.html
226+
/// [box]: ../../alloc/boxed/struct.Box.html
227+
/// [string]: ../../alloc/string/struct.String.html
228+
/// [rc]: ../../alloc/rc/struct.Rc.html
229+
/// [cow]: ../../alloc/borrow/enum.Cow.html
146230
///
147231
/// # Examples
148232
///

0 commit comments

Comments
 (0)