Rollup merge of #117495 - compiler-errors:unsize-docs, r=lcnr

Clarify `Unsize` documentation

The documentation erroneously says that:

```rust
/// - Types implementing a trait `Trait` also implement `Unsize<dyn Trait>`.
/// - Structs `Foo<..., T, ...>` implement `Unsize<Foo<..., U, ...>>` if all of these conditions
///   are met:
///   - `T: Unsize<U>`.
///   - Only the last field of `Foo` has a type involving `T`.
///   - `Bar<T>: Unsize<Bar<U>>`, where `Bar<T>` stands for the actual type of that last field.
```

Specifically, `T: Unsize<U>` is not required to hold -- only the final field must implement `FinalField<T>: Unsize<FinalField<U>>`. This can be demonstrated by the test I added.

---

Second commit fleshes out the documentation a lot more.
This commit is contained in:
Matthias Krüger 2023-11-02 15:31:21 +01:00 committed by GitHub
commit 9575625835
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 6 deletions

View File

@ -155,12 +155,18 @@ pub trait Sized {
/// Those implementations are: /// Those implementations are:
/// ///
/// - Arrays `[T; N]` implement `Unsize<[T]>`. /// - Arrays `[T; N]` implement `Unsize<[T]>`.
/// - Types implementing a trait `Trait` also implement `Unsize<dyn Trait>`. /// - A type implements `Unsize<dyn Trait + 'a>` if all of these conditions are met:
/// - Structs `Foo<..., T, ...>` implement `Unsize<Foo<..., U, ...>>` if all of these conditions /// - The type implements `Trait`.
/// are met: /// - `Trait` is object safe.
/// - `T: Unsize<U>`. /// - The type is sized.
/// - Only the last field of `Foo` has a type involving `T`. /// - The type outlives `'a`.
/// - `Bar<T>: Unsize<Bar<U>>`, where `Bar<T>` stands for the actual type of that last field. /// - Structs `Foo<..., T1, ..., Tn, ...>` implement `Unsize<Foo<..., U1, ..., Un, ...>>`
/// where any number of (type and const) parameters may be changed if all of these conditions
/// are met:
/// - Only the last field of `Foo` has a type involving the parameters `T1`, ..., `Tn`.
/// - All other parameters of the struct are equal.
/// - `Field<T1, ..., Tn>: Unsize<Field<U1, ..., Un>>`, where `Field<...>` stands for the actual
/// type of the struct's last field.
/// ///
/// `Unsize` is used along with [`ops::CoerceUnsized`] to allow /// `Unsize` is used along with [`ops::CoerceUnsized`] to allow
/// "user-defined" containers such as [`Rc`] to contain dynamically-sized /// "user-defined" containers such as [`Rc`] to contain dynamically-sized

View File

@ -0,0 +1,29 @@
// check-pass
struct Foo<T, U>
where
(T, U): Trait,
{
f: <(T, U) as Trait>::Assoc,
}
trait Trait {
type Assoc: ?Sized;
}
struct Count<const N: usize>;
impl<const N: usize> Trait for (i32, Count<N>) {
type Assoc = [(); N];
}
impl<'a> Trait for (u32, ()) {
type Assoc = [()];
}
// Test that we can unsize several trait params in creative ways.
fn unsize<const N: usize>(x: &Foo<i32, Count<N>>) -> &Foo<u32, ()> {
x
}
fn main() {}