1 // Like `projection-bound-cycle.rs` but this avoids using
2 // `feature(trivial_bounds)`.
3 
4 #![feature(generic_associated_types)]
5 
6 trait Print {
print()7     fn print();
8 }
9 
10 trait Foo {
11     type Item: Sized where <Self as Foo>::Item: Sized;
12 }
13 
14 struct Number<T> { t: T }
15 
16 impl<T> Foo for Number<T> {
17     // Well-formedness checks require that the following
18     // goal is true:
19     // ```
20     // if ([T]: Sized) { # if the where clauses hold
21     //     [T]: Sized # then the bound on the associated type hold
22     // }
23     // ```
24     // which it is :)
25     type Item where [T]: Sized = [T];
26 }
27 
28 struct OnlySized<T> where T: Sized { f: T }
29 impl<T> Print for OnlySized<T> {
print()30     fn print() {
31         println!("{}", std::mem::size_of::<T>());
32     }
33 }
34 
35 trait Bar {
36     type Assoc: Print;
37 }
38 
39 impl<T> Bar for T where T: Foo {
40     // This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires
41     // knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We
42     // can use the bound on `Foo::Item` for this, but that requires
43     // `wf(<T as Foo>::Item)`, which is an invalid cycle.
44     type Assoc = OnlySized<<T as Foo>::Item>;
45     //~^ ERROR overflow evaluating the requirement `<T as Foo>::Item: Sized`
46 }
47 
foo<T: Print>()48 fn foo<T: Print>() {
49     T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed
50 }
51 
bar<T: Bar>()52 fn bar<T: Bar>() {
53     // we have `FromEnv(T: Bar)` hence
54     // `<T as Bar>::Assoc` is well-formed and
55     // `Implemented(<T as Bar>::Assoc: Print)` hold
56     foo::<<T as Bar>::Assoc>()
57 }
58 
main()59 fn main() {
60     bar::<Number<u8>>()
61 }
62