about summary refs log tree commit diff
path: root/tests/ui/closures
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2025-07-04 23:26:19 -0700
committerGitHub <noreply@github.com>2025-07-04 23:26:19 -0700
commitb1234daf8c949d77a81a2f27102c9554a1ce7a8d (patch)
treeb2051ed4175a31c3f2953c5d565b3bfe819db817 /tests/ui/closures
parent733b47ea4b1b86216f14ef56e49440c33933f230 (diff)
parent1daba456361d0bbac3d0bd9e0f11b7784d20ebe5 (diff)
downloadrust-b1234daf8c949d77a81a2f27102c9554a1ce7a8d.tar.gz
rust-b1234daf8c949d77a81a2f27102c9554a1ce7a8d.zip
Rollup merge of #142440 - Kivooeo:tf14, r=tgross35
`tests/ui`: A New Order [14/N]

> [!NOTE]
>
> Intermediate commits are intended to help review, but will be squashed prior to merge.

Some `tests/ui/` housekeeping, to trim down number of tests directly under `tests/ui/`. Part of rust-lang/rust#133895.

r? `@jieyouxu`
Diffstat (limited to 'tests/ui/closures')
-rw-r--r--tests/ui/closures/closure-capture-after-clone.rs39
-rw-r--r--tests/ui/closures/closure-last-use-move.rs33
-rw-r--r--tests/ui/closures/closure-upvar-last-use-analysis.rs32
3 files changed, 104 insertions, 0 deletions
diff --git a/tests/ui/closures/closure-capture-after-clone.rs b/tests/ui/closures/closure-capture-after-clone.rs
new file mode 100644
index 00000000000..29fba147909
--- /dev/null
+++ b/tests/ui/closures/closure-capture-after-clone.rs
@@ -0,0 +1,39 @@
+//! Regression test for issue #1399
+//!
+//! This tests that when a variable is used (via clone) and then later
+//! captured by a closure, the last-use analysis doesn't incorrectly optimize
+//! the earlier use as a "last use" and perform an invalid move.
+//!
+//! The sequence being tested:
+//! 1. Create variable `k`
+//! 2. Use `k.clone()` for some purpose
+//! 3. Later capture `k` in a closure
+//!
+//! The analysis must not treat step 2 as the "last use" since step 3 needs `k`.
+//!
+//! See: https://github.com/rust-lang/rust/issues/1399
+
+//@ run-pass
+
+struct A {
+    _a: Box<isize>,
+}
+
+pub fn main() {
+    fn invoke<F>(f: F)
+    where
+        F: FnOnce(),
+    {
+        f();
+    }
+
+    let k: Box<_> = 22.into();
+
+    // This clone should NOT be treated as "last use" of k
+    // even though k is not used again until the closure
+    let _u = A { _a: k.clone() };
+
+    // Here k is actually captured by the closure
+    // The last-use analyzer must have accounted for this when processing the clone above
+    invoke(|| println!("{}", k.clone()));
+}
diff --git a/tests/ui/closures/closure-last-use-move.rs b/tests/ui/closures/closure-last-use-move.rs
new file mode 100644
index 00000000000..f5b99d87f09
--- /dev/null
+++ b/tests/ui/closures/closure-last-use-move.rs
@@ -0,0 +1,33 @@
+//! Regression test for issue #1818
+//! last-use analysis in closures should allow moves instead of requiring copies.
+//!
+//! The original issue was that the compiler incorrectly flagged certain return values
+//! in anonymous functions/closures as requiring copies of non-copyable values, when
+//! they should have been treated as moves (since they were the last use of the value).
+//!
+//! See: https://github.com/rust-lang/rust/issues/1818
+
+//@ run-pass
+
+fn apply<T, F>(s: String, mut f: F) -> T
+where
+    F: FnMut(String) -> T
+{
+    fn g<T, F>(s: String, mut f: F) -> T
+    where
+        F: FnMut(String) -> T
+    {
+        f(s)
+    }
+
+    g(s, |v| {
+        let r = f(v);
+        r // This should be a move, not requiring copy
+    })
+}
+
+pub fn main() {
+    // Actually test the functionality
+    let result = apply(String::from("test"), |s| s.len());
+    assert_eq!(result, 4);
+}
diff --git a/tests/ui/closures/closure-upvar-last-use-analysis.rs b/tests/ui/closures/closure-upvar-last-use-analysis.rs
new file mode 100644
index 00000000000..2c3e349437d
--- /dev/null
+++ b/tests/ui/closures/closure-upvar-last-use-analysis.rs
@@ -0,0 +1,32 @@
+//! Regression test for issue #1399
+//!
+//! This tests that the compiler's last-use analysis correctly handles variables
+//! that are captured by closures (upvars). The original issue was that the analysis
+//! would incorrectly optimize variable usage as "last use" and perform moves, even when
+//! the variable was later needed by a closure that captured it.
+//!
+//! See: https://github.com/rust-lang/rust/issues/1399
+
+//@ run-pass
+
+struct A {
+    _a: Box<isize>,
+}
+
+fn foo() -> Box<dyn FnMut() -> isize + 'static> {
+    let k: Box<_> = Box::new(22);
+
+    // This use of k.clone() should not be treated as a "last use"
+    // even though the closure below doesn't actually capture k
+    let _u = A { _a: k.clone() };
+
+    // The closure doesn't actually use k, but the analyzer needs to handle
+    // the potential capture scenario correctly
+    let result = || 22;
+
+    Box::new(result)
+}
+
+pub fn main() {
+    assert_eq!(foo()(), 22);
+}