about summary refs log tree commit diff
path: root/tests/ui/repeat-expr/copy-check-deferred-before-fallback.rs
blob: 23b13348f5a671c39b9467cd22f89768334817e5 (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
//@ check-pass

// Test when deferring repeat expr checks to end of typechecking whether they're
// checked before integer fallback occurs. We accomplish this by having the repeat
// expr check allow inference progress on an ambiguous goal, where the ambiguous goal
// would fail if the inference variable was fallen back to `i32`. This test will
// pass if we check repeat exprs before integer fallback.

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

impl Clone for Foo<u32> {
    fn clone(&self) -> Self {
        Foo(PhantomData)
    }
}
impl Copy for Foo<u32> {}

trait Trait {}

// Two impls just to ensure that `?int: Trait` wont itself succeed by unifying with
// a self type on an impl here. It also ensures that integer fallback would actually
// be valid for all of the stalled goals incase that's ever something we take into account.
impl Trait for i32 {}
impl Trait for u32 {}

fn make_goal<T: Trait>(_: &T) {}
fn tie<T>(_: &T, _: &[Foo<T>; 2]) {}

fn main() {
    let a = 1;
    // `?int: Trait`
    make_goal(&a);

    // Deferred `Foo<?int>: Copy` requirement
    let b: [Foo<_>; 2] = [Foo(PhantomData); _];
    tie(&a, &b);

    // If fallback doesn't occur:
    // - `Foo<?int>; 2`is > 1, needs copy
    // - `Foo<?int>: Copy` infers `?int=u32`
    // - stalled goal `?int: Trait` can now make progress and succeed

    // If fallback occurs:
    // - `Foo<i32>; 2` is > 1, needs copy
    // - `Foo<i32>: Copy` doesn't hold -> error
}