| # [`CoerceUnsized`](https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html) | |
| `CoerceUnsized` is primarily concerned with data containers. When a struct | |
| (typically, a smart pointer) implements `CoerceUnsized`, that means that the | |
| data it points to is being unsized. | |
| Some implementors of `CoerceUnsized` include: | |
| * `&T` | |
| * `Arc<T>` | |
| * `Box<T>` | |
| This trait is (eventually) intended to be implemented by user-written smart | |
| pointers, and there are rules about when a type is allowed to implement | |
| `CoerceUnsized` that are explained in the trait's documentation. | |
| # [`Unsize`](https://doc.rust-lang.org/std/marker/trait.Unsize.html) | |
| To contrast, the `Unsize` trait is concerned the actual types that are allowed | |
| to be unsized. | |
| This is not intended to be implemented by users ever, since `Unsize` does not | |
| instruct the compiler (namely codegen) *how* to unsize a type, just whether it | |
| is allowed to be unsized. This is paired somewhat intimately with codegen | |
| which must understand how types are represented and unsized. | |
| ## Primitive unsizing implementations | |
| Built-in implementations are provided for: | |
| * `T` -> `dyn Trait + 'a` when `T: Trait` (and `T: Sized + 'a`, and `Trait` | |
| is dyn-compatible[^2]). | |
| * `[T; N]` -> `[T]` | |
| ## Structural implementations | |
| There is one implementation of `Unsize` which can be thought of as | |
| structural: | |
| * `Struct<.., Pi, .., Pj, ..>: Unsize<Struct<.., Ui, .., Uj, ..>>` given | |
| `TailField<Pi, .., Pj>: Unsize<Ui, .. Uj>`, which allows the tail field of a | |
| struct to be unsized if it is the only field that mentions generic parameters | |
| `Pi`, .., `Pj` (which don't need to be contiguous). | |
| The rules for struct unsizing are slightly complicated, since they | |
| may allow more than one parameter to be changed (not necessarily unsized) and | |
| are best stated in terms of the tail field of the struct. | |
| (Tuple unsizing was previously implemented behind the feature gate | |
| `unsized_tuple_coercion`, but the implementation was removed by [#137728].) | |
| [#137728]: https://github.com/rust-lang/rust/pull/137728 | |
| ## Upcasting implementations | |
| Two things are called "upcasting" internally: | |
| 1. True upcasting `dyn SubTrait` -> `dyn SuperTrait` (this also allows | |
| dropping auto traits and adjusting lifetimes, as below). | |
| 2. Dropping auto traits and adjusting the lifetimes of dyn trait | |
| *without changing the principal[^1]*: | |
| `dyn Trait + AutoTraits... + 'a` -> `dyn Trait + NewAutoTraits... + 'b` | |
| when `AutoTraits` ⊇ `NewAutoTraits`, and `'a: 'b`. | |
| These may seem like different operations, since (1.) includes adjusting the | |
| vtable of a dyn trait, while (2.) is a no-op. However, to the type system, | |
| these are handled with much the same code. | |
| This built-in implementation of `Unsize` is the most involved, particularly | |
| after [it was reworked](https://github.com/rust-lang/rust/pull/114036) to | |
| support the complexities of associated types. | |
| Specifically, the upcasting algorithm involves: For each supertrait of the | |
| source dyn trait's principal (including itself)... | |
| 1. Unify the super trait ref with the principal of the target (making sure | |
| we only ever upcast to a true supertrait, and never [via an impl]). | |
| 2. For every auto trait in the target, check that it's present in the source | |
| (allowing us to drop auto traits, but never gain new ones). | |
| 3. For every projection in the target, check that it unifies with a single | |
| projection in the source (since there may be more than one given | |
| `trait Sub: Sup<.., A = i32> + Sup<.., A = u32>`). | |
| [via an impl]: https://github.com/rust-lang/rust/blob/f3457dbf84cd86d284454d12705861398ece76c3/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs#L19 | |
| Specifically, (3.) prevents a choice of projection bound to guide inference | |
| unnecessarily, though it may guide inference when it is unambiguous. | |
| [^1]: The principal is the one non-auto trait of a `dyn Trait`. | |
| [^2]: Formerly known as "object safe". |