about summary refs log tree commit diff
path: root/tests/ui/repeat-expr/copy-check-deferred-after-fallback.rs
blob: a6bd5b299c96a70c2275b084b6867ac8394b49ba (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
// Test when deferring repeat expr copy checks to end of typechecking whether they're
// checked before integer fallback occurs or not. We accomplish this by having a repeat
// count that can only be inferred after integer fallback has occured. This test will
// pass if we were to check repeat exprs after integer fallback.

use std::marker::PhantomData;
struct Foo<T>(PhantomData<T>);

// We impl Copy/Clone for multiple (but not all) substitutions
// to ensure that `Foo<?int>: Copy` can't be proven on the basis
// of there only being one applying impl.
impl Clone for Foo<u32> {
    fn clone(&self) -> Self {
        Foo(PhantomData)
    }
}
impl Clone for Foo<i32> {
    fn clone(&self) -> Self {
        Foo(PhantomData)
    }
}
impl Copy for Foo<u32> {}
impl Copy for Foo<i32> {}

trait Trait<const N: usize> {}

// We impl `Trait` for both `i32` and `u32` to avoid being able
// to prove `?int: Trait<?n>` from there only being one impl.
impl Trait<1> for i32 {}
impl Trait<2> for u32 {}

fn tie_and_make_goal<const N: usize, T: Trait<N>>(_: &T, _: &[Foo<T>; N]) {}

fn main() {
    let a = 1;
    // Deferred repeat expr `Foo<?int>; ?n`
    let b = [Foo(PhantomData); _];
    //~^ ERROR: type annotations needed for `[Foo<{integer}>; _]`

    // Introduces a `?int: Trait<?n>` goal
    tie_and_make_goal(&a, &b);

    // If fallback doesn't occur:
    // - `Foo<?int>; ?n`is ambig as repeat count is unknown -> error

    // If fallback occurs:
    // - `?int` inferred to `i32`
    // - `?int: Trait<?n>` becomes `i32: Trait<?n>` wihhc infers `?n=1`
    // - Repeat expr check `Foo<?int>; ?n` is now `Foo<i32>; 1`
    // - `Foo<i32>; 1` doesn't require `Foo<i32>: Copy`
}