diff options
| author | Boxy <rust@boxyuwu.dev> | 2025-04-10 13:02:07 +0100 |
|---|---|---|
| committer | Boxy <rust@boxyuwu.dev> | 2025-05-21 20:38:49 +0100 |
| commit | 52f2c45dee5211418e762789ad63e3ae56d9f3bf (patch) | |
| tree | c51a6e65c6aec37dbb3d9e42f55c177b858cdb3f /tests/ui/repeat-expr | |
| parent | f60bab475e47e84bb188e463b6a17894a57092c4 (diff) | |
| download | rust-52f2c45dee5211418e762789ad63e3ae56d9f3bf.tar.gz rust-52f2c45dee5211418e762789ad63e3ae56d9f3bf.zip | |
Properly test whether repeat expr checks are pre/post integer fallback
Diffstat (limited to 'tests/ui/repeat-expr')
4 files changed, 74 insertions, 82 deletions
diff --git a/tests/ui/repeat-expr/copy-check-deferred-after-fallback.rs b/tests/ui/repeat-expr/copy-check-deferred-after-fallback.rs index d9ad93541ec..3f310f07de0 100644 --- a/tests/ui/repeat-expr/copy-check-deferred-after-fallback.rs +++ b/tests/ui/repeat-expr/copy-check-deferred-after-fallback.rs @@ -1,37 +1,53 @@ #![feature(generic_arg_infer)] -// Test that would start passing if we defer repeat expr copy checks to end of -// typechecking and they're checked after integer fallback occurs. We accomplish -// this by contriving a situation where integer fallback allows progress to be -// made on a trait goal that infers the length of a repeat expr. +// 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 NotCopy; +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> {} -impl Trait<2> for u32 {} +// 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 make_goal<T: Trait<N>, const N: usize>(_: &T, _: [NotCopy; N]) {} +fn tie_and_make_goal<const N: usize, T: Trait<N>>(_: &T, _: &[Foo<T>; N]) {} fn main() { let a = 1; - let b = [NotCopy; _]; - //~^ ERROR: type annotations needed - - // a is of type `?y` - // b is of type `[NotCopy; ?x]` - // there is a goal ?y: Trait<?x>` with two candidates: - // - `i32: Trait<1>`, ?y=i32 ?x=1 which doesnt require `NotCopy: Copy` - // - `u32: Trait<2>` ?y=u32 ?x=2 which requires `NotCopy: Copy` - make_goal(&a, b); - - // final repeat expr checks: - // - // `NotCopy; ?x` - // - succeeds if fallback happens before repeat exprs as `i32: Trait<?x>` infers `?x=1` - // - fails if repeat expr checks happen first as `?x` is unconstrained so cannot be - // structurally resolved + // 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` } diff --git a/tests/ui/repeat-expr/copy-check-deferred-after-fallback.stderr b/tests/ui/repeat-expr/copy-check-deferred-after-fallback.stderr index 2a0cb3fb7a3..103b074dda7 100644 --- a/tests/ui/repeat-expr/copy-check-deferred-after-fallback.stderr +++ b/tests/ui/repeat-expr/copy-check-deferred-after-fallback.stderr @@ -1,13 +1,13 @@ -error[E0282]: type annotations needed for `[NotCopy; _]` - --> $DIR/copy-check-deferred-after-fallback.rs:21:9 +error[E0282]: type annotations needed for `[Foo<{integer}>; _]` + --> $DIR/copy-check-deferred-after-fallback.rs:39:9 | -LL | let b = [NotCopy; _]; - | ^ ------- type must be known at this point +LL | let b = [Foo(PhantomData); _]; + | ^ ---------------- type must be known at this point | help: consider giving `b` an explicit type, where the value of const parameter `N` is specified | -LL | let b: [_; N] = [NotCopy; _]; - | ++++++++ +LL | let b: [Foo<{integer}>; N] = [Foo(PhantomData); _]; + | +++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/repeat-expr/copy-check-deferred-before-fallback.rs b/tests/ui/repeat-expr/copy-check-deferred-before-fallback.rs index bf519febb30..b81997a3c9f 100644 --- a/tests/ui/repeat-expr/copy-check-deferred-before-fallback.rs +++ b/tests/ui/repeat-expr/copy-check-deferred-before-fallback.rs @@ -1,16 +1,13 @@ +//@ check-pass #![feature(generic_arg_infer)] -// Test that if we defer repeat expr copy checks to end of typechecking they're -// checked before integer fallback occurs. We accomplish this by contriving a -// situation where we have a goal that can be proven either via another repeat expr -// check or by integer fallback. In the integer fallback case an array length would -// be inferred to `2` requiring `NotCopy: Copy`, and in the repeat expr case it would -// be inferred to `1`. +// 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 wecheck repeat exprs before integer fallback. use std::marker::PhantomData; - -struct NotCopy; - struct Foo<T>(PhantomData<T>); impl Clone for Foo<u32> { @@ -18,41 +15,34 @@ impl Clone for Foo<u32> { Foo(PhantomData) } } - impl Copy for Foo<u32> {} -fn tie<T>(_: &T, _: [Foo<T>; 2]) {} - -trait Trait<const N: usize> {} +trait Trait {} -impl Trait<2> for i32 {} -impl Trait<1> for u32 {} +// 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<N>, const N: usize>(_: &T, _: [NotCopy; N]) {} +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); - let c = [NotCopy; _]; - //~^ ERROR: type annotations needed for `[NotCopy; _]` - - // a is of type `?y` - // b is of type `[Foo<?y>; 2]` - // c is of type `[NotCopy; ?x]` - // there is a goal ?y: Trait<?x>` with two candidates: - // - `i32: Trait<2>`, ?y=i32 ?x=2 which requires `NotCopy: Copy` when expr checks happen - // - `u32: Trait<1>` ?y=u32 ?x=1 which doesnt require `NotCopy: Copy` - make_goal(&a, c); - - // final repeat expr checks: - // - // `Foo<?y>; 2` - // - Foo<?y>: Copy - // - requires ?y=u32 - // - // `NotCopy; ?x` - // - fails if fallback happens before repeat exprs as `i32: Trait<?x>` infers `?x=2` - // - succeeds if repeat expr checks happen first as `?y=u32` means `u32: Trait<?x>` - // infers `?x=1` + 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 } diff --git a/tests/ui/repeat-expr/copy-check-deferred-before-fallback.stderr b/tests/ui/repeat-expr/copy-check-deferred-before-fallback.stderr deleted file mode 100644 index d6189329c92..00000000000 --- a/tests/ui/repeat-expr/copy-check-deferred-before-fallback.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0282]: type annotations needed for `[NotCopy; _]` - --> $DIR/copy-check-deferred-before-fallback.rs:37:9 - | -LL | let c = [NotCopy; _]; - | ^ ------- type must be known at this point - | -help: consider giving `c` an explicit type, where the value of const parameter `N` is specified - | -LL | let c: [_; N] = [NotCopy; _]; - | ++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0282`. |
