| # [`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". |