diff options
| author | Jubilee <workingjubilee@gmail.com> | 2025-07-04 23:26:19 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-04 23:26:19 -0700 |
| commit | b1234daf8c949d77a81a2f27102c9554a1ce7a8d (patch) | |
| tree | b2051ed4175a31c3f2953c5d565b3bfe819db817 /tests/ui/closures | |
| parent | 733b47ea4b1b86216f14ef56e49440c33933f230 (diff) | |
| parent | 1daba456361d0bbac3d0bd9e0f11b7784d20ebe5 (diff) | |
| download | rust-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.rs | 39 | ||||
| -rw-r--r-- | tests/ui/closures/closure-last-use-move.rs | 33 | ||||
| -rw-r--r-- | tests/ui/closures/closure-upvar-last-use-analysis.rs | 32 |
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); +} |
