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>()48fn foo<T: Print>() { 49 T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed 50 } 51 bar<T: Bar>()52fn 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()59fn main() { 60 bar::<Number<u8>>() 61 } 62