Skip to content

Commit cd0eabf

Browse files
Add some documentation for unsizing
1 parent 7c28596 commit cd0eabf

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

src/traits/unsize.md

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# [`CoerceUnsized`](https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html)
2+
3+
`CoerceUnsized` is primarily concerned with data containers. When a struct
4+
(typically, a smart pointer) implements `CoerceUnsized`, that means that the
5+
data it points to is being unsized.
6+
7+
Some implementors of `CoerceUnsized` include:
8+
* `&T`
9+
* `Arc<T>`
10+
* `Box<T>`
11+
12+
This trait is (eventually) intended to be implemented by user-written smart
13+
pointers, and there are rules about when a type is allowed to implement
14+
`CoerceUnsized` that are explained in the trait's documentation.
15+
16+
# [`Unsize`](https://doc.rust-lang.org/std/marker/trait.Unsize.html)
17+
18+
To contrast, the `Unsize` trait is concerned the actual types that are allowed
19+
to be unsized.
20+
21+
This is not intended to be implemented by users ever, since `Unsize` does not
22+
instruct the compiler (namely codegen) *how* to unsize a type, just whether it
23+
is allowed to be unsized. This is paired somewhat intimately with codegen
24+
which must understand how types are represented and unsized.
25+
26+
## Primitive unsizing implementations
27+
28+
Built-in implementations are provided for:
29+
* `T` -> `dyn Trait + 'a` when `T: Trait` (and `T: Sized + 'a`, and `Trait`
30+
is object safe).
31+
* `[T; N]` -> `[T]`
32+
33+
## Structural implementations
34+
35+
There are two implementations of `Unsize` which can be thought of as
36+
structural:
37+
* `(A1, A2, .., An): Unsize<(A1, A2, .., U)>` given `An: Unsize<U>`, which
38+
allows the tail field of a tuple to be unsized. This is gated behind the
39+
[`unsized_tuple_coercion`] feature.
40+
* `Struct<.., Pi, .., Pj, ..>: Unsize<Struct<.., Ui, .., Uj, ..>>` given
41+
`TailField<Pi, .., Pj>: Unsize<Ui, .. Uj>`, which allows the tail field of a
42+
struct to be unsized if it is the only field that mentions generic parameters
43+
`Pi`, .., `Pj` (which don't need to be contiguous).
44+
45+
The rules for the latter implementation are slightly complicated, since they
46+
may allow more than one parameter to be changed (not necessarily unsized) and
47+
are best stated in terms of the tail field of the struct.
48+
49+
[`unsized_tuple_coercion`]: https://doc.rust-lang.org/beta/unstable-book/language-features/unsized-tuple-coercion.html
50+
51+
## Upcasting implementations
52+
53+
Two things are called "upcasting" internally:
54+
1. True upcasting `dyn SubTrait` -> `dyn SuperTrait` (this also allows
55+
dropping auto traits and adjusting lifetimes, as below).
56+
2. Dropping auto traits and adjusting the lifetimes of dyn trait
57+
*without changing the principal[^1]*:
58+
`dyn Trait + AutoTraits... + 'a` -> `dyn Trait + NewAutoTraits... + 'b`
59+
when `AutoTraits``NewAutoTraits`, and `'a: 'b`.
60+
61+
These may seem like different operations, since (1.) includes adjusting the
62+
vtable of a dyn trait, while (2.) is a no-op. However, to the type system,
63+
these are handled with much the same code.
64+
65+
This built-in implementation of `Unsize` is the most involved, particularly
66+
after [it was reworked](https://github.com/rust-lang/rust/pull/114036) to
67+
support the complexities of associated types.
68+
69+
Specifically, the upcasting algorithm involves: For each supertrait of the
70+
source dyn trait's principal (including itself)...
71+
1. Unify the super trait ref with the principal of the target (making sure
72+
we only ever upcast to a true supertrait, and never [via an impl]).
73+
2. For every auto trait in the source, check that it's present in the principal
74+
(allowing us to drop auto traits, but never gain new ones).
75+
3. For every projection in the source, check that it unifies with a single
76+
projection in the target (since there may be more than one given
77+
`trait Sub: Sup<.., A = i32> + Sup<.., A = u32>`).
78+
79+
[via an impl]: https://github.com/rust-lang/rust/blob/f3457dbf84cd86d284454d12705861398ece76c3/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs#L19
80+
81+
Specifically, (3.) prevents a choice of projection bound to guide inference
82+
unnecessarily, though it may guide inference when it is unambiguous.
83+
84+
[^1]: The principal is the one non-auto trait of a `dyn Trait`.

0 commit comments

Comments
 (0)