summaryrefslogtreecommitdiffstats
path: root/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs')
-rw-r--r--src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs
new file mode 100644
index 000000000..794d677c8
--- /dev/null
+++ b/src/test/ui/generic-associated-types/projection-bound-cycle-generic.rs
@@ -0,0 +1,61 @@
+// Like `projection-bound-cycle.rs` but this avoids using
+// `feature(trivial_bounds)`.
+
+#![feature(generic_associated_types)]
+
+trait Print {
+ fn print();
+}
+
+trait Foo {
+ type Item: Sized where <Self as Foo>::Item: Sized;
+}
+
+struct Number<T> { t: T }
+
+impl<T> Foo for Number<T> {
+ // Well-formedness checks require that the following
+ // goal is true:
+ // ```
+ // if ([T]: Sized) { # if the where clauses hold
+ // [T]: Sized # then the bound on the associated type hold
+ // }
+ // ```
+ // which it is :)
+ type Item = [T] where [T]: Sized;
+}
+
+struct OnlySized<T> where T: Sized { f: T }
+impl<T> Print for OnlySized<T> {
+ fn print() {
+ println!("{}", std::mem::size_of::<T>());
+ }
+}
+
+trait Bar {
+ type Assoc: Print;
+}
+
+impl<T> Bar for T where T: Foo {
+ // This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires
+ // knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We
+ // can use the bound on `Foo::Item` for this, but that requires
+ // `wf(<T as Foo>::Item)`, which is an invalid cycle.
+ type Assoc = OnlySized<<T as Foo>::Item>;
+ //~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized`
+}
+
+fn foo<T: Print>() {
+ T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed
+}
+
+fn bar<T: Bar>() {
+ // we have `FromEnv(T: Bar)` hence
+ // `<T as Bar>::Assoc` is well-formed and
+ // `Implemented(<T as Bar>::Assoc: Print)` hold
+ foo::<<T as Bar>::Assoc>()
+}
+
+fn main() {
+ bar::<Number<u8>>()
+}