diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-11-02 15:31:21 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-02 15:31:21 +0100 |
| commit | 957562583538aa4934957121fef155cbf7324d56 (patch) | |
| tree | 7a420e8318d5fe21441796feba4f0f3eedffbd1e | |
| parent | 298edd6d463c4c4f32cff3e6a18fd569854ba5c5 (diff) | |
| parent | 1221b7b652a9859340fad0cd6db78c7493f3847f (diff) | |
| download | rust-957562583538aa4934957121fef155cbf7324d56.tar.gz rust-957562583538aa4934957121fef155cbf7324d56.zip | |
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.
| -rw-r--r-- | library/core/src/marker.rs | 18 | ||||
| -rw-r--r-- | tests/ui/unsized/unsize-coerce-multiple-adt-params.rs | 29 |
2 files changed, 41 insertions, 6 deletions
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index d396a707b55..13437d8f961 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -155,12 +155,18 @@ pub trait Sized { /// Those implementations are: /// /// - Arrays `[T; N]` implement `Unsize<[T]>`. -/// - 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. +/// - A type implements `Unsize<dyn Trait + 'a>` if all of these conditions are met: +/// - The type implements `Trait`. +/// - `Trait` is object safe. +/// - The type is sized. +/// - The type outlives `'a`. +/// - 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 /// "user-defined" containers such as [`Rc`] to contain dynamically-sized diff --git a/tests/ui/unsized/unsize-coerce-multiple-adt-params.rs b/tests/ui/unsized/unsize-coerce-multiple-adt-params.rs new file mode 100644 index 00000000000..eba341ff284 --- /dev/null +++ b/tests/ui/unsized/unsize-coerce-multiple-adt-params.rs @@ -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() {} |
