diff options
Diffstat (limited to 'tests/ui/closures')
| -rw-r--r-- | tests/ui/closures/closure-capture-after-clone.rs | 40 | ||||
| -rw-r--r-- | tests/ui/closures/closure-last-use-move.rs | 42 | ||||
| -rw-r--r-- | tests/ui/closures/closure-upvar-last-use-analysis.rs | 27 |
3 files changed, 81 insertions, 28 deletions
diff --git a/tests/ui/closures/closure-capture-after-clone.rs b/tests/ui/closures/closure-capture-after-clone.rs index 6e07895f1d3..29fba147909 100644 --- a/tests/ui/closures/closure-capture-after-clone.rs +++ b/tests/ui/closures/closure-capture-after-clone.rs @@ -1,13 +1,39 @@ -//@ run-pass +//! 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 -#![allow(dead_code)] -// Make sure #1399 stays fixed +//@ run-pass -struct A { a: Box<isize> } +struct A { + _a: Box<isize>, +} pub fn main() { - fn invoke<F>(f: F) where F: FnOnce() { f(); } + fn invoke<F>(f: F) + where + F: FnOnce(), + { + f(); + } + let k: Box<_> = 22.into(); - let _u = A {a: k.clone()}; - invoke(|| println!("{}", k.clone()) ) + + // 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 index 4a166b97bda..f5b99d87f09 100644 --- a/tests/ui/closures/closure-last-use-move.rs +++ b/tests/ui/closures/closure-last-use-move.rs @@ -1,21 +1,33 @@ -//@ run-pass - -#![allow(dead_code)] -#![allow(unused_parens)] -// Issue #1818 +//! 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 lp<T, F>(s: String, mut f: F) -> T where F: FnMut(String) -> T { - while false { - let r = f(s); - return (r); +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) } - panic!(); -} -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 }) + g(s, |v| { + let r = f(v); + r // This should be a move, not requiring copy + }) } -pub fn main() {} +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 index 23c263c9805..2c3e349437d 100644 --- a/tests/ui/closures/closure-upvar-last-use-analysis.rs +++ b/tests/ui/closures/closure-upvar-last-use-analysis.rs @@ -1,14 +1,29 @@ -//@ run-pass +//! 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 -#![allow(dead_code)] -// Make sure #1399 stays fixed +//@ run-pass -struct A { a: Box<isize> } +struct A { + _a: Box<isize>, +} fn foo() -> Box<dyn FnMut() -> isize + 'static> { let k: Box<_> = Box::new(22); - let _u = A {a: k.clone()}; - let result = || 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) } |
