1 // check-pass
2
3 // This test checks that we're correctly dealing with inductive cycles
4 // with canonical inference variables.
5
6 trait Trait<T, U> {}
7
8 trait IsNotU32 {}
9 impl IsNotU32 for i32 {}
10 impl<T: IsNotU32, U> Trait<T, U> for () // impl 1
11 where
12 (): Trait<U, T>
13 {}
14
15 impl<T> Trait<u32, T> for () {} // impl 2
16
17 // If we now check whether `(): Trait<?0, ?1>` holds this has to
18 // result in ambiguity as both `for<T> (): Trait<u32, T>` and `(): Trait<i32, u32>`
19 // applies. The remainder of this test asserts that.
20
21 // If we were to error on inductive cycles with canonical inference variables
22 // this would be wrong:
23
24 // (): Trait<?0, ?1>
25 // - impl 1
26 // - ?0: IsNotU32 // ambig
27 // - (): Trait<?1, ?0> // canonical cycle -> err
28 // - ERR
29 // - impl 2
30 // - OK ?0 == u32
31 //
32 // Result: OK ?0 == u32.
33
34 // (): Trait<i32, u32>
35 // - impl 1
36 // - i32: IsNotU32 // ok
37 // - (): Trait<u32, i32>
38 // - impl 1
39 // - u32: IsNotU32 // err
40 // - ERR
41 // - impl 2
42 // - OK
43 // - OK
44 // - impl 2 (trivial ERR)
45 //
46 // Result OK
47
48 // This would mean that `(): Trait<?0, ?1>` is not complete,
49 // which is unsound if we're in coherence.
50
implements_trait<T, U>() -> (T, U) where (): Trait<T, U>,51 fn implements_trait<T, U>() -> (T, U)
52 where
53 (): Trait<T, U>,
54 {
55 todo!()
56 }
57
58 // A hack to only constrain the infer vars after first checking
59 // the `(): Trait<_, _>`.
60 trait Constrain<T> {}
61 impl<T> Constrain<T> for T {}
constrain<T: Constrain<U>, U>(_: U)62 fn constrain<T: Constrain<U>, U>(_: U) {}
63
main()64 fn main() {
65 let (x, y) = implements_trait::<_, _>();
66
67 constrain::<i32, _>(x);
68 constrain::<u32, _>(y);
69 }
70