| //@ check-pass | |
| // This test checks that we're correctly dealing with inductive cycles | |
| // with canonical inference variables. | |
| trait Trait<T, U> {} | |
| trait IsNotU32 {} | |
| impl IsNotU32 for i32 {} | |
| impl<T: IsNotU32, U> Trait<T, U> for () // impl 1 | |
| where | |
| (): Trait<U, T> | |
| {} | |
| impl<T> Trait<u32, T> for () {} // impl 2 | |
| // If we now check whether `(): Trait<?0, ?1>` holds this has to | |
| // result in ambiguity as both `for<T> (): Trait<u32, T>` and `(): Trait<i32, u32>` | |
| // applies. The remainder of this test asserts that. | |
| // If we were to error on inductive cycles with canonical inference variables | |
| // this would be wrong: | |
| // (): Trait<?0, ?1> | |
| // - impl 1 | |
| // - ?0: IsNotU32 // ambig | |
| // - (): Trait<?1, ?0> // canonical cycle -> err | |
| // - ERR | |
| // - impl 2 | |
| // - OK ?0 == u32 | |
| // | |
| // Result: OK ?0 == u32. | |
| // (): Trait<i32, u32> | |
| // - impl 1 | |
| // - i32: IsNotU32 // ok | |
| // - (): Trait<u32, i32> | |
| // - impl 1 | |
| // - u32: IsNotU32 // err | |
| // - ERR | |
| // - impl 2 | |
| // - OK | |
| // - OK | |
| // - impl 2 (trivial ERR) | |
| // | |
| // Result OK | |
| // This would mean that `(): Trait<?0, ?1>` is not complete, | |
| // which is unsound if we're in coherence. | |
| fn implements_trait<T, U>() -> (T, U) | |
| where | |
| (): Trait<T, U>, | |
| { | |
| todo!() | |
| } | |
| // A hack to only constrain the infer vars after first checking | |
| // the `(): Trait<_, _>`. | |
| trait Constrain<T> {} | |
| impl<T> Constrain<T> for T {} | |
| fn constrain<T: Constrain<U>, U>(_: U) {} | |
| fn main() { | |
| let (x, y) = implements_trait::<_, _>(); | |
| constrain::<i32, _>(x); | |
| constrain::<u32, _>(y); | |
| } |