|
1 | 1 | #![feature(generic_arg_infer)]
|
2 | 2 |
|
3 |
| -// Test that would start passing if we defer repeat expr copy checks to end of |
4 |
| -// typechecking and they're checked after integer fallback occurs. We accomplish |
5 |
| -// this by contriving a situation where integer fallback allows progress to be |
6 |
| -// made on a trait goal that infers the length of a repeat expr. |
| 3 | +// Test when deferring repeat expr copy checks to end of typechecking whether they're |
| 4 | +// checked before integer fallback occurs or not. We accomplish this by having a repeat |
| 5 | +// count that can only be inferred after integer fallback has occured. This test will |
| 6 | +// pass if we were to check repeat exprs after integer fallback. |
7 | 7 |
|
8 | 8 | use std::marker::PhantomData;
|
9 |
| - |
10 |
| -struct NotCopy; |
| 9 | +struct Foo<T>(PhantomData<T>); |
| 10 | + |
| 11 | +// We impl Copy/Clone for multiple (but not all) substitutions |
| 12 | +// to ensure that `Foo<?int>: Copy` can't be proven on the basis |
| 13 | +// of there only being one applying impl. |
| 14 | +impl Clone for Foo<u32> { |
| 15 | + fn clone(&self) -> Self { |
| 16 | + Foo(PhantomData) |
| 17 | + } |
| 18 | +} |
| 19 | +impl Clone for Foo<i32> { |
| 20 | + fn clone(&self) -> Self { |
| 21 | + Foo(PhantomData) |
| 22 | + } |
| 23 | +} |
| 24 | +impl Copy for Foo<u32> {} |
| 25 | +impl Copy for Foo<i32> {} |
11 | 26 |
|
12 | 27 | trait Trait<const N: usize> {}
|
13 | 28 |
|
14 |
| -impl Trait<2> for u32 {} |
| 29 | +// We impl `Trait` for both `i32` and `u32` to avoid being able |
| 30 | +// to prove `?int: Trait<?n>` from there only being one impl. |
15 | 31 | impl Trait<1> for i32 {}
|
| 32 | +impl Trait<2> for u32 {} |
16 | 33 |
|
17 |
| -fn make_goal<T: Trait<N>, const N: usize>(_: &T, _: [NotCopy; N]) {} |
| 34 | +fn tie_and_make_goal<const N: usize, T: Trait<N>>(_: &T, _: &[Foo<T>; N]) {} |
18 | 35 |
|
19 | 36 | fn main() {
|
20 | 37 | let a = 1;
|
21 |
| - let b = [NotCopy; _]; |
22 |
| - //~^ ERROR: type annotations needed |
23 |
| - |
24 |
| - // a is of type `?y` |
25 |
| - // b is of type `[NotCopy; ?x]` |
26 |
| - // there is a goal ?y: Trait<?x>` with two candidates: |
27 |
| - // - `i32: Trait<1>`, ?y=i32 ?x=1 which doesnt require `NotCopy: Copy` |
28 |
| - // - `u32: Trait<2>` ?y=u32 ?x=2 which requires `NotCopy: Copy` |
29 |
| - make_goal(&a, b); |
30 |
| - |
31 |
| - // final repeat expr checks: |
32 |
| - // |
33 |
| - // `NotCopy; ?x` |
34 |
| - // - succeeds if fallback happens before repeat exprs as `i32: Trait<?x>` infers `?x=1` |
35 |
| - // - fails if repeat expr checks happen first as `?x` is unconstrained so cannot be |
36 |
| - // structurally resolved |
| 38 | + // Deferred repeat expr `Foo<?int>; ?n` |
| 39 | + let b = [Foo(PhantomData); _]; |
| 40 | + //~^ ERROR: type annotations needed for `[Foo<{integer}>; _]` |
| 41 | + |
| 42 | + // Introduces a `?int: Trait<?n>` goal |
| 43 | + tie_and_make_goal(&a, &b); |
| 44 | + |
| 45 | + // If fallback doesn't occur: |
| 46 | + // - `Foo<?int>; ?n`is ambig as repeat count is unknown -> error |
| 47 | + |
| 48 | + // If fallback occurs: |
| 49 | + // - `?int` inferred to `i32` |
| 50 | + // - `?int: Trait<?n>` becomes `i32: Trait<?n>` wihhc infers `?n=1` |
| 51 | + // - Repeat expr check `Foo<?int>; ?n` is now `Foo<i32>; 1` |
| 52 | + // - `Foo<i32>; 1` doesn't require `Foo<i32>: Copy` |
37 | 53 | }
|
0 commit comments