about summary refs log tree commit diff
path: root/tests/ui/repeat-expr
diff options
context:
space:
mode:
authorBoxy <rust@boxyuwu.dev>2025-04-10 13:02:07 +0100
committerBoxy <rust@boxyuwu.dev>2025-05-21 20:38:49 +0100
commit52f2c45dee5211418e762789ad63e3ae56d9f3bf (patch)
treec51a6e65c6aec37dbb3d9e42f55c177b858cdb3f /tests/ui/repeat-expr
parentf60bab475e47e84bb188e463b6a17894a57092c4 (diff)
downloadrust-52f2c45dee5211418e762789ad63e3ae56d9f3bf.tar.gz
rust-52f2c45dee5211418e762789ad63e3ae56d9f3bf.zip
Properly test whether repeat expr checks are pre/post integer fallback
Diffstat (limited to 'tests/ui/repeat-expr')
-rw-r--r--tests/ui/repeat-expr/copy-check-deferred-after-fallback.rs64
-rw-r--r--tests/ui/repeat-expr/copy-check-deferred-after-fallback.stderr12
-rw-r--r--tests/ui/repeat-expr/copy-check-deferred-before-fallback.rs66
-rw-r--r--tests/ui/repeat-expr/copy-check-deferred-before-fallback.stderr14
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`.