diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/associated-types/defaults-suitability.rs | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/associated-types/defaults-suitability.rs')
-rw-r--r-- | src/test/ui/associated-types/defaults-suitability.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs new file mode 100644 index 000000000..504c957d9 --- /dev/null +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -0,0 +1,101 @@ +//! Checks that associated type defaults are properly validated. +//! +//! This means: +//! * Default types are checked against where clauses on the assoc. type +//! (eg. `type Assoc: Clone = NotClone`) + +#![feature(associated_type_defaults)] + +struct NotClone; + +// Assoc. type bounds must hold for the default type +trait Tr { + type Ty: Clone = NotClone; + //~^ ERROR the trait bound `NotClone: Clone` is not satisfied +} + +// Where-clauses defined on the trait must also be considered +trait Tr2 +where + Self::Ty: Clone, +{ + type Ty = NotClone; + //~^ ERROR the trait bound `NotClone: Clone` is not satisfied +} + +// Involved type parameters must fulfill all bounds required by defaults that mention them +trait Foo<T> { + type Bar: Clone = Vec<T>; + //~^ ERROR the trait bound `T: Clone` is not satisfied +} + +trait Bar: Sized { + // `(): Foo<Self>` might hold for some possible impls but not all. + type Assoc: Foo<Self> = (); + //~^ ERROR the trait bound `(): Foo<Self>` is not satisfied +} + +trait IsU8<T> {} +impl<T> IsU8<u8> for T {} + +// Test that mentioning the assoc. type inside where clauses is not allowed +trait C where + Vec<Self::Assoc>: Clone, + Self::Assoc: IsU8<Self::Assoc>, + bool: IsU8<Self::Assoc>, +{ + type Assoc = u8; +} + +// Test that we get all expected errors if that default is unsuitable +trait D where + Vec<Self::Assoc>: Clone, + Self::Assoc: IsU8<Self::Assoc>, + bool: IsU8<Self::Assoc>, +{ + type Assoc = NotClone; + //~^ ERROR the trait bound `NotClone: IsU8<NotClone>` is not satisfied +} + +// Test behavior of the check when defaults refer to other defaults: + +// Shallow substitution rejects this trait since `Baz` isn't guaranteed to be +// `Clone`. +trait Foo2<T> { + type Bar: Clone = Vec<Self::Baz>; + //~^ ERROR the trait bound `<Self as Foo2<T>>::Baz: Clone` is not satisfied + type Baz = T; +} + +// Adding a `T: Clone` bound doesn't help since the requirement doesn't see `T` +// because of the shallow substitution. If we did a deep substitution instead, +// this would be accepted. +trait Foo25<T: Clone> { + type Bar: Clone = Vec<Self::Baz>; + //~^ ERROR the trait bound `<Self as Foo25<T>>::Baz: Clone` is not satisfied + type Baz = T; +} + +// Adding the `Baz: Clone` bound isn't enough since the default is type +// parameter `T`, which also might not be `Clone`. +trait Foo3<T> +where + Self::Bar: Clone, + Self::Baz: Clone, +{ + type Bar = Vec<Self::Baz>; + type Baz = T; + //~^ ERROR the trait bound `T: Clone` is not satisfied +} + +// This one finally works, with `Clone` bounds on all assoc. types and the type +// parameter. +trait Foo4<T> +where + T: Clone, +{ + type Bar: Clone = Vec<Self::Baz>; + type Baz: Clone = T; +} + +fn main() {} |