summaryrefslogtreecommitdiffstats
path: root/tests/ui/traits/solver-cycles/inductive-canonical-cycle.rs
blob: 5449f5f00d52a8699d7132f7b7e86ce3bf5f8cc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// 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);
}