Skip to content

Commit 9b0d1c1

Browse files
committed
Properly test whether repeat expr checks are pre/post integer fallback
1 parent 1c58fc4 commit 9b0d1c1

4 files changed

+74
-82
lines changed
Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,53 @@
11
#![feature(generic_arg_infer)]
22

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.
77

88
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> {}
1126

1227
trait Trait<const N: usize> {}
1328

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.
1531
impl Trait<1> for i32 {}
32+
impl Trait<2> for u32 {}
1633

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]) {}
1835

1936
fn main() {
2037
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`
3753
}

tests/ui/repeat-expr/copy-check-deferred-after-fallback.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
error[E0282]: type annotations needed for `[NotCopy; _]`
2-
--> $DIR/copy-check-deferred-after-fallback.rs:21:9
1+
error[E0282]: type annotations needed for `[Foo<{integer}>; _]`
2+
--> $DIR/copy-check-deferred-after-fallback.rs:39:9
33
|
4-
LL | let b = [NotCopy; _];
5-
| ^ ------- type must be known at this point
4+
LL | let b = [Foo(PhantomData); _];
5+
| ^ ---------------- type must be known at this point
66
|
77
help: consider giving `b` an explicit type, where the value of const parameter `N` is specified
88
|
9-
LL | let b: [_; N] = [NotCopy; _];
10-
| ++++++++
9+
LL | let b: [Foo<{integer}>; N] = [Foo(PhantomData); _];
10+
| +++++++++++++++++++++
1111

1212
error: aborting due to 1 previous error
1313

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,48 @@
1+
//@ check-pass
12
#![feature(generic_arg_infer)]
23

3-
// Test that if we defer repeat expr copy checks to end of typechecking they're
4-
// checked before integer fallback occurs. We accomplish this by contriving a
5-
// situation where we have a goal that can be proven either via another repeat expr
6-
// check or by integer fallback. In the integer fallback case an array length would
7-
// be inferred to `2` requiring `NotCopy: Copy`, and in the repeat expr case it would
8-
// be inferred to `1`.
4+
// Test when deferring repeat expr checks to end of typechecking whether they're
5+
// checked before integer fallback occurs. We accomplish this by having the repeat
6+
// expr check allow inference progress on an ambiguous goal, where the ambiguous goal
7+
// would fail if the inference variable was fallen back to `i32`. This test will
8+
// pass if wecheck repeat exprs before integer fallback.
99

1010
use std::marker::PhantomData;
11-
12-
struct NotCopy;
13-
1411
struct Foo<T>(PhantomData<T>);
1512

1613
impl Clone for Foo<u32> {
1714
fn clone(&self) -> Self {
1815
Foo(PhantomData)
1916
}
2017
}
21-
2218
impl Copy for Foo<u32> {}
2319

24-
fn tie<T>(_: &T, _: [Foo<T>; 2]) {}
25-
26-
trait Trait<const N: usize> {}
20+
trait Trait {}
2721

28-
impl Trait<2> for i32 {}
29-
impl Trait<1> for u32 {}
22+
// Two impls just to ensure that `?int: Trait` wont itself succeed by unifying with
23+
// a self type on an impl here. It also ensures that integer fallback would actually
24+
// be valid for all of the stalled goals incase that's ever something we take into account.
25+
impl Trait for i32 {}
26+
impl Trait for u32 {}
3027

31-
fn make_goal<T: Trait<N>, const N: usize>(_: &T, _: [NotCopy; N]) {}
28+
fn make_goal<T: Trait>(_: &T) {}
29+
fn tie<T>(_: &T, _: &[Foo<T>; 2]) {}
3230

3331
fn main() {
3432
let a = 1;
33+
// `?int: Trait`
34+
make_goal(&a);
35+
36+
// Deferred `Foo<?int>: Copy` requirement
3537
let b: [Foo<_>; 2] = [Foo(PhantomData); _];
36-
tie(&a, b);
37-
let c = [NotCopy; _];
38-
//~^ ERROR: type annotations needed for `[NotCopy; _]`
39-
40-
// a is of type `?y`
41-
// b is of type `[Foo<?y>; 2]`
42-
// c is of type `[NotCopy; ?x]`
43-
// there is a goal ?y: Trait<?x>` with two candidates:
44-
// - `i32: Trait<2>`, ?y=i32 ?x=2 which requires `NotCopy: Copy` when expr checks happen
45-
// - `u32: Trait<1>` ?y=u32 ?x=1 which doesnt require `NotCopy: Copy`
46-
make_goal(&a, c);
47-
48-
// final repeat expr checks:
49-
//
50-
// `Foo<?y>; 2`
51-
// - Foo<?y>: Copy
52-
// - requires ?y=u32
53-
//
54-
// `NotCopy; ?x`
55-
// - fails if fallback happens before repeat exprs as `i32: Trait<?x>` infers `?x=2`
56-
// - succeeds if repeat expr checks happen first as `?y=u32` means `u32: Trait<?x>`
57-
// infers `?x=1`
38+
tie(&a, &b);
39+
40+
// If fallback doesn't occur:
41+
// - `Foo<?int>; 2`is > 1, needs copy
42+
// - `Foo<?int>: Copy` infers `?int=u32`
43+
// - stalled goal `?int: Trait` can now make progress and succeed
44+
45+
// If fallback occurs:
46+
// - `Foo<i32>; 2` is > 1, needs copy
47+
// - `Foo<i32>: Copy` doesn't hold -> error
5848
}

tests/ui/repeat-expr/copy-check-deferred-before-fallback.stderr

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)