Skip to content

Commit 6316e43

Browse files
authored
Rollup merge of #38816 - Manishearth:coercion-doc, r=GuillaumeGomez
Add more docs for CoerceUnsized and Unsize here be dragons r? @ubsan @steveklabnik
2 parents e9068c6 + 07e844f commit 6316e43

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

src/doc/nomicon/coercions.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Coercion is allowed between the following types:
1717
* `&T` to `*const T`
1818
* `&mut T` to `*mut T`
1919
* Unsizing: `T` to `U` if `T` implements `CoerceUnsized<U>`
20+
* Deref coercion: Expression `&x` of type `&T` to `&*x` of type `&U` if `T` derefs to `U` (i.e. `T: Deref<Target=U>`)
2021

2122
`CoerceUnsized<Pointer<U>> for Pointer<T> where T: Unsize<U>` is implemented
2223
for all pointer types (including smart pointers like Box and Rc). Unsize is
@@ -27,8 +28,9 @@ only implemented automatically, and enables the following transformations:
2728
* `Foo<..., T, ...>` => `Foo<..., U, ...>` where:
2829
* `T: Unsize<U>`
2930
* `Foo` is a struct
30-
* Only the last field of `Foo` has type `T`
31+
* Only the last field of `Foo` has type involving `T`
3132
* `T` is not part of the type of any other fields
33+
* `Bar<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
3234

3335
Coercions occur at a *coercion site*. Any location that is explicitly typed
3436
will cause a coercion to its type. If inference is necessary, the coercion will

src/libcore/marker.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,26 @@ pub trait Sized {
100100
///
101101
/// All implementations of `Unsize` are provided automatically by the compiler.
102102
///
103+
/// `Unsize` is implemented for:
104+
///
105+
/// - `[T; N]` is `Unsize<[T]>`
106+
/// - `T` is `Unsize<Trait>` when `T: Trait`
107+
/// - `Foo<..., T, ...>` is `Unsize<Foo<..., U, ...>>` if:
108+
/// - `T: Unsize<U>`
109+
/// - Foo is a struct
110+
/// - Only the last field of `Foo` has a type involving `T`
111+
/// - `T` is not part of the type of any other fields
112+
/// - `Bar<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
113+
///
103114
/// `Unsize` is used along with [`ops::CoerceUnsized`][coerceunsized] to allow
104115
/// "user-defined" containers such as [`rc::Rc`][rc] to contain dynamically-sized
105-
/// types. See the [DST coercion RFC][RFC982] for more details.
116+
/// types. See the [DST coercion RFC][RFC982] and [the nomicon entry on coercion][nomicon-coerce]
117+
/// for more details.
106118
///
107119
/// [coerceunsized]: ../ops/trait.CoerceUnsized.html
108120
/// [rc]: ../../std/rc/struct.Rc.html
109121
/// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
122+
110123
#[unstable(feature = "unsize", issue = "27732")]
111124
#[lang="unsize"]
112125
pub trait Unsize<T: ?Sized> {

src/libcore/ops.rs

+29
Original file line numberDiff line numberDiff line change
@@ -2710,6 +2710,35 @@ mod impls {
27102710

27112711
/// Trait that indicates that this is a pointer or a wrapper for one,
27122712
/// where unsizing can be performed on the pointee.
2713+
///
2714+
/// See the [DST coercion RfC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce]
2715+
/// for more details.
2716+
///
2717+
/// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize<U>`
2718+
/// by converting from a thin pointer to a fat pointer.
2719+
///
2720+
/// For custom types, the coercion here works by coercing `Foo<T>` to `Foo<U>`
2721+
/// provided an impl of `CoerceUnsized<Foo<U>> for Foo<T>` exists.
2722+
/// Such an impl can only be written if `Foo<T>` has only a single non-phantomdata
2723+
/// field involving `T`. If the type of that field is `Bar<T>`, an implementation
2724+
/// of `CoerceUnsized<Bar<U>> for Bar<T>` must exist. The coercion will work by
2725+
/// by coercing the `Bar<T>` field into `Bar<U>` and filling in the rest of the fields
2726+
/// from `Foo<T>` to create a `Foo<U>`. This will effectively drill down to a pointer
2727+
/// field and coerce that.
2728+
///
2729+
/// Generally, for smart pointers you will implement
2730+
/// `CoerceUnsized<Ptr<U>> for Ptr<T> where T: Unsize<U>, U: ?Sized`, with an
2731+
/// optional `?Sized` bound on `T` itself. For wrapper types that directly embed `T`
2732+
/// like `Cell<T>` and `RefCell<T>`, you
2733+
/// can directly implement `CoerceUnsized<Wrap<U>> for Wrap<T> where T: CoerceUnsized<U>`.
2734+
/// This will let coercions of types like `Cell<Box<T>>` work.
2735+
///
2736+
/// [`Unsize`][unsize] is used to mark types which can be coerced to DSTs if behind
2737+
/// pointers. It is implemented automatically by the compiler.
2738+
///
2739+
/// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
2740+
/// [unsize]: ../marker/trait.Unsize.html
2741+
/// [nomicon-coerce]: ../../nomicon/coercions.html
27132742
#[unstable(feature = "coerce_unsized", issue = "27732")]
27142743
#[lang="coerce_unsized"]
27152744
pub trait CoerceUnsized<T> {

0 commit comments

Comments
 (0)