diff options
| author | bors <bors@rust-lang.org> | 2021-07-11 03:50:28 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-07-11 03:50:28 +0000 |
| commit | 9f2e753b2fd1f614c64ba451ff816f50a3ac2edd (patch) | |
| tree | fdc8ab47b9a2482b94bd24d5f715afba918f1189 /src | |
| parent | 99f8efec46c72cb11418f858ae142baa5f3582a9 (diff) | |
| parent | 08c616741c6eff64443cc50d2ec8db9663ff61d8 (diff) | |
Auto merge of #86965 - sexxi-goose:rfc2229-improve-lint, r=nikomatsakis,lqd
Improves migrations lint for RFC2229
This PR improves the current disjoint capture migration lint by providing more information on why drop order or auto trait implementation for a closure is impacted by the use of the new feature.
The drop order migration lint will now look something like this:
```
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/significant_drop.rs:163:21
|
LL | let c = || {
| ^^
...
LL | tuple.0;
| ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
...
LL | }
| - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
```
The auto trait migration lint will now look something like this:
```
error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure
--> $DIR/auto_traits.rs:14:19
|
LL | thread::spawn(move || unsafe {
| ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
...
LL | *fptr.0 = 20;
| ------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
```
r? `@nikomatsakis`
Closes https://github.com/rust-lang/project-rfc-2229/issues/54
Diffstat (limited to 'src')
24 files changed, 1031 insertions, 290 deletions
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed index 134d07c400b..e2b7b8f0275 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.fixed @@ -1,5 +1,6 @@ // run-rustfix #![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here use std::thread; @@ -11,9 +12,12 @@ fn test_send_trait() { let mut f = 10; let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || { let _ = &fptr; unsafe { - //~^ ERROR: `Send` trait implementation + //~^ ERROR: `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0` } }); } @@ -28,9 +32,12 @@ fn test_sync_trait() { let f = CustomInt(&mut f as *mut i32); let fptr = SyncPointer(f); thread::spawn(move || { let _ = &fptr; unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation + //~^ ERROR: `Sync`, `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0` } }); } @@ -49,9 +56,12 @@ impl Clone for U { fn test_clone_trait() { let f = U(S(String::from("Hello World")), T(0)); let c = || { let _ = &f; - //~^ ERROR: `Clone` trait implementation, and drop order + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; + //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1` println!("{:?}", f_1.0); }; @@ -59,6 +69,7 @@ fn test_clone_trait() { c_clone(); } +//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure fn main() { test_send_trait(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs index b48a724f052..6c56ca27475 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.rs @@ -1,5 +1,6 @@ // run-rustfix #![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here use std::thread; @@ -11,9 +12,12 @@ fn test_send_trait() { let mut f = 10; let fptr = SendPointer(&mut f as *mut i32); thread::spawn(move || unsafe { - //~^ ERROR: `Send` trait implementation + //~^ ERROR: `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0` }); } @@ -28,9 +32,12 @@ fn test_sync_trait() { let f = CustomInt(&mut f as *mut i32); let fptr = SyncPointer(f); thread::spawn(move || unsafe { - //~^ ERROR: `Sync`, `Send` trait implementation + //~^ ERROR: `Sync`, `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `fptr` to be fully captured *fptr.0.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0` }); } @@ -49,9 +56,12 @@ impl Clone for U { fn test_clone_trait() { let f = U(S(String::from("Hello World")), T(0)); let c = || { - //~^ ERROR: `Clone` trait implementation, and drop order + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured let f_1 = f.1; + //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1` println!("{:?}", f_1.0); }; @@ -59,6 +69,7 @@ fn test_clone_trait() { c_clone(); } +//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure fn main() { test_send_trait(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr index 3d3dde15412..9c954b1465d 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr @@ -1,13 +1,11 @@ -error: `Send` trait implementation will change in Rust 2021 - --> $DIR/auto_traits.rs:13:19 +error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure + --> $DIR/auto_traits.rs:14:19 | -LL | thread::spawn(move || unsafe { - | ___________________^ -LL | | -LL | | -LL | | *fptr.0 = 20; -LL | | }); - | |_____^ +LL | thread::spawn(move || unsafe { + | ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send` +... +LL | *fptr.0 = 20; + | ------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0` | note: the lint level is defined here --> $DIR/auto_traits.rs:2:9 @@ -20,20 +18,19 @@ help: add a dummy let to cause `fptr` to be fully captured LL | thread::spawn(move || { let _ = &fptr; unsafe { LL | LL | +LL | +LL | LL | *fptr.0 = 20; -LL | } }); - | + ... -error: `Sync`, `Send` trait implementation will change in Rust 2021 - --> $DIR/auto_traits.rs:30:19 +error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure + --> $DIR/auto_traits.rs:34:19 | -LL | thread::spawn(move || unsafe { - | ___________________^ -LL | | -LL | | -LL | | *fptr.0.0 = 20; -LL | | }); - | |_____^ +LL | thread::spawn(move || unsafe { + | ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send` +... +LL | *fptr.0.0 = 20; + | --------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0` | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `fptr` to be fully captured @@ -41,21 +38,22 @@ help: add a dummy let to cause `fptr` to be fully captured LL | thread::spawn(move || { let _ = &fptr; unsafe { LL | LL | +LL | +LL | LL | *fptr.0.0 = 20; -LL | } }); - | + ... -error: `Clone` trait implementation, and drop order will change in Rust 2021 - --> $DIR/auto_traits.rs:51:13 +error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order + --> $DIR/auto_traits.rs:58:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let f_1 = f.1; -LL | | println!("{:?}", f_1.0); -LL | | }; - | |_____^ +LL | let c = || { + | ^^ in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone` +... +LL | let f_1 = f.1; + | --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1` +... +LL | } + | - in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `f` to be fully captured @@ -63,10 +61,10 @@ help: add a dummy let to cause `f` to be fully captured LL | let c = || { let _ = &f; LL | LL | +LL | +LL | LL | let f_1 = f.1; -LL | println!("{:?}", f_1.0); -LL | }; - | + ... error: aborting due to 3 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed index 51d9c4881af..e836f27cd7a 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.fixed @@ -18,12 +18,18 @@ fn test1_all_need_migration() { //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2.0; + //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure +//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure // String implements drop and therefore should be migrated. // But in this test cases, `t2` is completely captured and when it is dropped won't be affected @@ -37,12 +43,16 @@ fn test2_only_precise_paths_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure // If a variable would've not been captured by value then it would've not been // dropped with the closure and therefore doesn't need migration. @@ -54,11 +64,13 @@ fn test3_only_by_value_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` println!("{}", t1.1); }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Copy types get copied into the closure instead of move. Therefore we don't need to // migrate then as their drop order isn't tied to the closure. @@ -73,11 +85,13 @@ fn test4_only_non_copy_types_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn test5_only_drop_types_need_migration() { struct S(i32, i32); @@ -92,11 +106,13 @@ fn test5_only_drop_types_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _s = s.0; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Since we are using a move closure here, both `t` and `t1` get moved // even though they are being used by ref inside the closure. @@ -108,10 +124,14 @@ fn test6_move_closures_non_copy_types_might_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{} {}", t1.1, t.1); + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` + //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure // Test migration analysis in case of Drop + Non Drop aggregates. // Note we need migration here only because the non-copy (because Drop type) is captured, @@ -124,10 +144,12 @@ fn test7_drop_non_drop_aggregate_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn main() { test1_all_need_migration(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs index c732cbb4fa5..fbf9b983f07 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.rs @@ -18,12 +18,18 @@ fn test1_all_need_migration() { //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2.0; + //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure +//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure // String implements drop and therefore should be migrated. // But in this test cases, `t2` is completely captured and when it is dropped won't be affected @@ -37,12 +43,16 @@ fn test2_only_precise_paths_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure // If a variable would've not been captured by value then it would've not been // dropped with the closure and therefore doesn't need migration. @@ -54,11 +64,13 @@ fn test3_only_by_value_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` println!("{}", t1.1); }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Copy types get copied into the closure instead of move. Therefore we don't need to // migrate then as their drop order isn't tied to the closure. @@ -73,11 +85,13 @@ fn test4_only_non_copy_types_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn test5_only_drop_types_need_migration() { struct S(i32, i32); @@ -92,11 +106,13 @@ fn test5_only_drop_types_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _s = s.0; }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Since we are using a move closure here, both `t` and `t1` get moved // even though they are being used by ref inside the closure. @@ -108,10 +124,14 @@ fn test6_move_closures_non_copy_types_might_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{} {}", t1.1, t.1); + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` + //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure +//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure // Test migration analysis in case of Drop + Non Drop aggregates. // Note we need migration here only because the non-copy (because Drop type) is captured, @@ -124,10 +144,12 @@ fn test7_drop_non_drop_aggregate_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn main() { test1_all_need_migration(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr index 89a2b0eb953..e9e4794cff5 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop.stderr @@ -1,15 +1,24 @@ -error: drop order will change in Rust 2021 +error: changes to closure capture in Rust 2021 will affect drop order --> $DIR/insignificant_drop.rs:15:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -... | -LL | | let _t2 = t2.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +LL | +LL | let _t1 = t1.0; + | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` +LL | +LL | let _t2 = t2.0; + | ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` +... +LL | } + | - + | | + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure + | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure | note: the lint level is defined here --> $DIR/insignificant_drop.rs:3:9 @@ -27,18 +36,23 @@ LL | LL | let _t = t.0; ... -error: drop order will change in Rust 2021 - --> $DIR/insignificant_drop.rs:35:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -... | -LL | | let _t2 = t2; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:41:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +LL | +LL | let _t1 = t1.0; + | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` +... +LL | } + | - + | | + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t`, `t1` to be fully captured @@ -48,21 +62,20 @@ LL | LL | LL | LL | let _t = t.0; -LL | let _t1 = t1.0; +LL | ... -error: drop order will change in Rust 2021 - --> $DIR/insignificant_drop.rs:52:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.0; -LL | | println!("{}", t1.1); -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:62:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured @@ -72,21 +85,20 @@ LL | LL | LL | LL | let _t = t.0; -LL | println!("{}", t1.1); +LL | ... -error: drop order will change in Rust 2021 - --> $DIR/insignificant_drop.rs:71:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.0; -LL | | let _t1 = t1.0; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:83:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured @@ -96,21 +108,20 @@ LL | LL | LL | LL | let _t = t.0; -LL | let _t1 = t1.0; +LL | ... -error: drop order will change in Rust 2021 - --> $DIR/insignificant_drop.rs:90:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.0; -LL | | let _s = s.0; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:104:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured @@ -120,20 +131,25 @@ LL | LL | LL | LL | let _t = t.0; -LL | let _s = s.0; +LL | ... -error: drop order will change in Rust 2021 - --> $DIR/insignificant_drop.rs:106:13 - | -LL | let c = move || { - | _____________^ -LL | | -LL | | -LL | | -LL | | println!("{} {}", t1.1, t.1); -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:122:13 + | +LL | let c = move || { + | ^^^^^^^ +... +LL | println!("{} {}", t1.1, t.1); + | ---- --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` + | | + | in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` +... +LL | } + | - + | | + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t1`, `t` to be fully captured @@ -143,20 +159,20 @@ LL | LL | LL | LL | println!("{} {}", t1.1, t.1); -LL | }; - | +LL | + ... -error: drop order will change in Rust 2021 - --> $DIR/insignificant_drop.rs:122:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop.rs:142:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured @@ -166,8 +182,8 @@ LL | LL | LL | LL | let _t = t.0; -LL | }; - | +LL | + ... error: aborting due to 7 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed index 8c85cd990d3..4626c04e9ba 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.fixed @@ -39,10 +39,12 @@ fn significant_drop_needs_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Even if a type implements an insignificant drop, if it's // elements have a significant drop then the overall type is @@ -57,10 +59,12 @@ fn generic_struct_with_significant_drop_needs_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure fn main() { significant_drop_needs_migration(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs index 17cee28e311..ebcf1551bac 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.rs @@ -39,10 +39,12 @@ fn significant_drop_needs_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Even if a type implements an insignificant drop, if it's // elements have a significant drop then the overall type is @@ -57,10 +59,12 @@ fn generic_struct_with_significant_drop_needs_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure fn main() { significant_drop_needs_migration(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr index 1d3bda03d0e..1e97ca34d16 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr @@ -1,14 +1,14 @@ -error: drop order will change in Rust 2021 +error: changes to closure capture in Rust 2021 will affect drop order --> $DIR/insignificant_drop_attr_migrations.rs:37:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | note: the lint level is defined here --> $DIR/insignificant_drop_attr_migrations.rs:3:9 @@ -23,20 +23,20 @@ LL | LL | LL | LL | let _t = t.0; -LL | }; - | +LL | + ... -error: drop order will change in Rust 2021 - --> $DIR/insignificant_drop_attr_migrations.rs:55:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/insignificant_drop_attr_migrations.rs:57:13 | -LL | let c = move || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.1; -LL | | }; - | |_____^ +LL | let c = move || { + | ^^^^^^^ +... +LL | let _t = t.1; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured @@ -46,8 +46,8 @@ LL | LL | LL | LL | let _t = t.1; -LL | }; - | +LL | + ... error: aborting due to 2 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed index c974299c153..f3c15a2e6b6 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.fixed @@ -21,20 +21,24 @@ fn closure_contains_block() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn closure_doesnt_contain_block() { let t = (Foo(0), Foo(0)); let c = || { let _ = &t; t.0 }; //~^ ERROR: drop order + //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn main() { closure_contains_block(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs index dd9556aa567..50936d15302 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.rs @@ -21,20 +21,24 @@ fn closure_contains_block() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn closure_doesnt_contain_block() { let t = (Foo(0), Foo(0)); let c = || t.0; //~^ ERROR: drop order + //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure fn main() { closure_contains_block(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr index 2d5e5e5e55c..f8f72d1580c 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr @@ -1,14 +1,14 @@ -error: drop order will change in Rust 2021 +error: changes to closure capture in Rust 2021 will affect drop order --> $DIR/migrations_rustfix.rs:19:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | note: the lint level is defined here --> $DIR/migrations_rustfix.rs:2:9 @@ -23,14 +23,19 @@ LL | LL | LL | LL | let _t = t.0; -LL | }; - | +LL | + ... -error: drop order will change in Rust 2021 - --> $DIR/migrations_rustfix.rs:31:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/migrations_rustfix.rs:33:13 | LL | let c = || t.0; - | ^^^^^^ + | ^^^--- + | | + | in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed index 7f49b460ef6..f24804018cd 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed @@ -1,6 +1,7 @@ // run-rustfix #![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here // ignore-wasm32-bare compiled with panic=abort by default #![feature(fn_traits)] #![feature(never_type)] @@ -17,9 +18,12 @@ where { let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { let _ = &f; - //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation + //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured f.0() + //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0` }); if let Ok(..) = result { panic!("diverging function returned"); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs index 3c654bec526..6a6a51c5132 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs @@ -1,6 +1,7 @@ // run-rustfix #![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here // ignore-wasm32-bare compiled with panic=abort by default #![feature(fn_traits)] #![feature(never_type)] @@ -17,9 +18,12 @@ where { let f = panic::AssertUnwindSafe(f); let result = panic::catch_unwind(move || { - //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation + //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `f` to be fully captured f.0() + //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0` }); if let Ok(..) = result { panic!("diverging function returned"); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr index dca5c454b83..6ee0d0d252a 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr @@ -1,13 +1,11 @@ -error: `UnwindSafe`, `RefUnwindSafe` trait implementation will change in Rust 2021 - --> $DIR/mir_calls_to_shims.rs:19:38 +error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnwindSafe` trait implementation for closure + --> $DIR/mir_calls_to_shims.rs:20:38 | -LL | let result = panic::catch_unwind(move || { - | ______________________________________^ -LL | | -LL | | -LL | | f.0() -LL | | }); - | |_____^ +LL | let result = panic::catch_unwind(move || { + | ^^^^^^^ in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe` +... +LL | f.0() + | --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0` | note: the lint level is defined here --> $DIR/mir_calls_to_shims.rs:3:9 @@ -20,9 +18,10 @@ help: add a dummy let to cause `f` to be fully captured LL | let result = panic::catch_unwind(move || { let _ = &f; LL | LL | +LL | +LL | LL | f.0() -LL | }); - | + ... error: aborting due to previous error diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed new file mode 100644 index 00000000000..98f578abc44 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed @@ -0,0 +1,138 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +use std::thread; + +struct S(String); + +#[derive(Clone)] +struct T(i32); + +struct U(S, T); + +impl Clone for U { + fn clone(&self) -> Self { + U(S(String::from("Hello World")), T(0)) + } +} + +fn test_multi_issues() { + let f1 = U(S(String::from("foo")), T(0)); + let f2 = U(S(String::from("bar")), T(0)); + let c = || { let _ = (&f1, &f2); + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f2.1; + //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure + +fn test_capturing_all_disjoint_fields_individually() { + let f1 = U(S(String::from("foo")), T(0)); + let c = || { let _ = &f1; + //~^ ERROR: `Clone` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f1.1; + }; + + let c_clone = c.clone(); + + c_clone(); +} + +struct U1(S, T, S); + +impl Clone for U1 { + fn clone(&self) -> Self { + U1(S(String::from("foo")), T(0), S(String::from("bar"))) + } +} + +fn test_capturing_several_disjoint_fields_individually_1() { + let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar"))); + let c = || { let _ = &f1; + //~^ ERROR: `Clone` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f1.2; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2` + }; + + let c_clone = c.clone(); + + c_clone(); +} + +fn test_capturing_several_disjoint_fields_individually_2() { + let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar"))); + let c = || { let _ = &f1; + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_1 = f1.1; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure + +struct SendPointer(*mut i32); +unsafe impl Send for SendPointer {} + +struct CustomInt(*mut i32); +struct SyncPointer(CustomInt); +unsafe impl Sync for SyncPointer {} +unsafe impl Send for CustomInt {} + +fn test_multi_traits_issues() { + let mut f1 = 10; + let f1 = CustomInt(&mut f1 as *mut i32); + let fptr1 = SyncPointer(f1); + + let mut f2 = 10; + let fptr2 = SendPointer(&mut f2 as *mut i32); + thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe { + //~^ ERROR: `Sync`, `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` + //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured + *fptr1.0.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0` + *fptr2.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0` + } }); +} + +fn main() { + test_multi_issues(); + test_capturing_all_disjoint_fields_individually(); + test_capturing_several_disjoint_fields_individually_1(); + test_capturing_several_disjoint_fields_individually_2(); + test_multi_traits_issues(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs new file mode 100644 index 00000000000..1577b91c960 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs @@ -0,0 +1,138 @@ +// run-rustfix +#![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here + +use std::thread; + +struct S(String); + +#[derive(Clone)] +struct T(i32); + +struct U(S, T); + +impl Clone for U { + fn clone(&self) -> Self { + U(S(String::from("Hello World")), T(0)) + } +} + +fn test_multi_issues() { + let f1 = U(S(String::from("foo")), T(0)); + let f2 = U(S(String::from("bar")), T(0)); + let c = || { + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f2.1; + //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure + +fn test_capturing_all_disjoint_fields_individually() { + let f1 = U(S(String::from("foo")), T(0)); + let c = || { + //~^ ERROR: `Clone` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_1 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f1.1; + }; + + let c_clone = c.clone(); + + c_clone(); +} + +struct U1(S, T, S); + +impl Clone for U1 { + fn clone(&self) -> Self { + U1(S(String::from("foo")), T(0), S(String::from("bar"))) + } +} + +fn test_capturing_several_disjoint_fields_individually_1() { + let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar"))); + let c = || { + //~^ ERROR: `Clone` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_2 = f1.2; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2` + }; + + let c_clone = c.clone(); + + c_clone(); +} + +fn test_capturing_several_disjoint_fields_individually_2() { + let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar"))); + let c = || { + //~^ ERROR: `Clone` trait implementation for closure and drop order + //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `f1` to be fully captured + let _f_0 = f1.0; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + let _f_1 = f1.1; + //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1` + }; + + let c_clone = c.clone(); + + c_clone(); +} +//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure + +struct SendPointer(*mut i32); +unsafe impl Send for SendPointer {} + +struct CustomInt(*mut i32); +struct SyncPointer(CustomInt); +unsafe impl Sync for SyncPointer {} +unsafe impl Send for CustomInt {} + +fn test_multi_traits_issues() { + let mut f1 = 10; + let f1 = CustomInt(&mut f1 as *mut i32); + let fptr1 = SyncPointer(f1); + + let mut f2 = 10; + let fptr2 = SendPointer(&mut f2 as *mut i32); + thread::spawn(move || unsafe { + //~^ ERROR: `Sync`, `Send` trait implementation for closure + //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` + //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send` + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured + *fptr1.0.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0` + *fptr2.0 = 20; + //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0` + }); +} + +fn main() { + test_multi_issues(); + test_capturing_all_disjoint_fields_individually(); + test_capturing_several_disjoint_fields_individually_1(); + test_capturing_several_disjoint_fields_individually_2(); + test_multi_traits_issues(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr new file mode 100644 index 00000000000..8a42683c1df --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr @@ -0,0 +1,134 @@ +error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order + --> $DIR/multi_diagnostics.rs:23:13 + | +LL | let c = || { + | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` +... +LL | let _f_1 = f1.0; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` +LL | +LL | let _f_2 = f2.1; + | ---- in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1` +... +LL | } + | - in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure + | +note: the lint level is defined here + --> $DIR/multi_diagnostics.rs:2:9 + | +LL | #![deny(rust_2021_incompatible_closure_captures)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> +help: add a dummy let to cause `f1`, `f2` to be fully captured + | +LL | let c = || { let _ = (&f1, &f2); +LL | +LL | +LL | +LL | +LL | let _f_1 = f1.0; + ... + +error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure + --> $DIR/multi_diagnostics.rs:42:13 + | +LL | let c = || { + | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` +... +LL | let _f_1 = f1.0; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` + | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> +help: add a dummy let to cause `f1` to be fully captured + | +LL | let c = || { let _ = &f1; +LL | +LL | +LL | +LL | +LL | let _f_1 = f1.0; + ... + +error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure + --> $DIR/multi_diagnostics.rs:67:13 + | +LL | let c = || { + | ^^ + | | + | in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` + | in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone` +... +LL | let _f_0 = f1.0; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` +LL | +LL | let _f_2 = f1.2; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2` + | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> +help: add a dummy let to cause `f1` to be fully captured + | +LL | let c = || { let _ = &f1; +LL | +LL | +LL | +LL | +LL | + ... + +error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order + --> $DIR/multi_diagnostics.rs:86:13 + | +LL | let c = || { + | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone` +... +LL | let _f_0 = f1.0; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0` +LL | +LL | let _f_1 = f1.1; + | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1` +... +LL | } + | - + | | + | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure + | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure + | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> +help: add a dummy let to cause `f1` to be fully captured + | +LL | let c = || { let _ = &f1; +LL | +LL | +LL | +LL | +LL | let _f_0 = f1.0; + ... + +error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure + --> $DIR/multi_diagnostics.rs:119:19 + | +LL | thread::spawn(move || unsafe { + | ^^^^^^^^^^^^^^ + | | + | in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send` + | in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send` +... +LL | *fptr1.0.0 = 20; + | ---------- in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0` +LL | +LL | *fptr2.0 = 20; + | -------- in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0` + | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> +help: add a dummy let to cause `fptr1`, `fptr2` to be fully captured + | +LL | thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe { +LL | +LL | +LL | +LL | +LL | + ... + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed index ba5e5b573f1..226172fb93e 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.fixed @@ -1,6 +1,7 @@ // run-rustfix #![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here #[derive(Debug)] struct Foo(i32); @@ -18,13 +19,16 @@ fn test_precise_analysis_drop_paths_not_captured_by_move() { let c = || { let _ = &t; //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t = &t.1; }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure struct S; impl Drop for S { @@ -40,14 +44,22 @@ fn test_precise_analysis_long_path_missing() { let c = || { let _ = &u; //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `u` to be fully captured let _x = u.0.0; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0` let _x = u.0.1; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1` let _x = u.1.0; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0` }; c(); } +//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure + fn main() { test_precise_analysis_drop_paths_not_captured_by_move(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs index 92b6f25c80d..7035abe6de0 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.rs @@ -1,6 +1,7 @@ // run-rustfix #![deny(rust_2021_incompatible_closure_captures)] +//~^ NOTE: the lint level is defined here #[derive(Debug)] struct Foo(i32); @@ -18,13 +19,16 @@ fn test_precise_analysis_drop_paths_not_captured_by_move() { let c = || { //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t = &t.1; }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure struct S; impl Drop for S { @@ -40,14 +44,22 @@ fn test_precise_analysis_long_path_missing() { let c = || { //~^ ERROR: drop order + //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `u` to be fully captured let _x = u.0.0; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0` let _x = u.0.1; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1` let _x = u.1.0; + //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0` }; c(); } +//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure + fn main() { test_precise_analysis_drop_paths_not_captured_by_move(); diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr index 2788207296f..5bf73ccc554 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr @@ -1,14 +1,14 @@ -error: drop order will change in Rust 2021 - --> $DIR/precise.rs:19:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/precise.rs:20:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _t = t.0; -LL | | let _t = &t.1; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | note: the lint level is defined here --> $DIR/precise.rs:3:9 @@ -21,23 +21,32 @@ help: add a dummy let to cause `t` to be fully captured LL | let c = || { let _ = &t; LL | LL | +LL | LL | let _t = t.0; -LL | let _t = &t.1; -LL | }; - | +LL | + ... -error: drop order will change in Rust 2021 - --> $DIR/precise.rs:41:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/precise.rs:45:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | let _x = u.0.0; -LL | | let _x = u.0.1; -LL | | let _x = u.1.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _x = u.0.0; + | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0` +LL | +LL | let _x = u.0.1; + | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1` +LL | +LL | let _x = u.1.0; + | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0` +... +LL | } + | - + | | + | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure + | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure + | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `u` to be fully captured @@ -45,9 +54,9 @@ help: add a dummy let to cause `u` to be fully captured LL | let c = || { let _ = &u; LL | LL | +LL | LL | let _x = u.0.0; -LL | let _x = u.0.1; -LL | let _x = u.1.0; +LL | ... error: aborting due to 2 previous errors diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed index 58ed2de26b3..236fdb9e26e 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed @@ -27,12 +27,18 @@ fn test1_all_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2.0; + //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure // String implements drop and therefore should be migrated. // But in this test cases, `t2` is completely captured and when it is dropped won't be affected @@ -46,12 +52,16 @@ fn test2_only_precise_paths_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2; }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure // If a variable would've not been captured by value then it would've not been // dropped with the closure and therefore doesn't need migration. @@ -63,11 +73,13 @@ fn test3_only_by_value_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` println!("{:?}", t1.1); }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // The root variable might not implement drop themselves but some path starting // at the root variable might implement Drop. @@ -81,10 +93,12 @@ fn test4_type_contains_drop_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Test migration analysis in case of Drop + Non Drop aggregates. // Note we need migration here only because the non-copy (because Drop type) is captured, @@ -97,10 +111,12 @@ fn test5_drop_non_drop_aggregate_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Test migration analysis in case of Significant and Insignificant Drop aggregates. fn test6_significant_insignificant_drop_aggregate_need_migration() { @@ -111,10 +127,12 @@ fn test6_significant_insignificant_drop_aggregate_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure // Since we are using a move closure here, both `t` and `t1` get moved // even though they are being used by ref inside the closure. @@ -127,10 +145,53 @@ fn test7_move_closures_non_copy_types_might_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{:?} {:?}", t1.1, t.1); + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` + //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure + + +fn test8_drop_order_and_blocks() { + { + let tuple = + (String::from("foo"), String::from("bar")); + { + let c = || { let _ = &tuple; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` + }; + + c(); + } + //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + } +} + +fn test9_drop_order_and_nested_closures() { + let tuple = + (String::from("foo"), String::from("bar")); + let b = || { + let c = || { let _ = &tuple; + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` + }; + + c(); + }; + //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + + b(); +} fn main() { test1_all_need_migration(); @@ -140,4 +201,6 @@ fn main() { test5_drop_non_drop_aggregate_need_migration(); test6_significant_insignificant_drop_aggregate_need_migration(); test7_move_closures_non_copy_types_might_need_migration(); + test8_drop_order_and_blocks(); + test9_drop_order_and_nested_closures(); } diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs index 0890fc1c212..a57f7aa565e 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs @@ -27,12 +27,18 @@ fn test1_all_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2.0; + //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure // String implements drop and therefore should be migrated. // But in this test cases, `t2` is completely captured and when it is dropped won't be affected @@ -46,12 +52,16 @@ fn test2_only_precise_paths_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t`, `t1` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` let _t1 = t1.0; + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` let _t2 = t2; }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure // If a variable would've not been captured by value then it would've not been // dropped with the closure and therefore doesn't need migration. @@ -63,11 +73,13 @@ fn test3_only_by_value_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` println!("{:?}", t1.1); }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // The root variable might not implement drop themselves but some path starting // at the root variable might implement Drop. @@ -81,10 +93,12 @@ fn test4_type_contains_drop_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Test migration analysis in case of Drop + Non Drop aggregates. // Note we need migration here only because the non-copy (because Drop type) is captured, @@ -97,10 +111,12 @@ fn test5_drop_non_drop_aggregate_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.0; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure // Test migration analysis in case of Significant and Insignificant Drop aggregates. fn test6_significant_insignificant_drop_aggregate_need_migration() { @@ -111,10 +127,12 @@ fn test6_significant_insignificant_drop_aggregate_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t` to be fully captured let _t = t.1; + //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure // Since we are using a move closure here, both `t` and `t1` get moved // even though they are being used by ref inside the closure. @@ -127,10 +145,53 @@ fn test7_move_closures_non_copy_types_might_need_migration() { //~| NOTE: for more information, see //~| HELP: add a dummy let to cause `t1`, `t` to be fully captured println!("{:?} {:?}", t1.1, t.1); + //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` + //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` }; c(); } +//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure +//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure + + +fn test8_drop_order_and_blocks() { + { + let tuple = + (String::from("foo"), String::from("bar")); + { + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` + }; + + c(); + } + //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + } +} + +fn test9_drop_order_and_nested_closures() { + let tuple = + (String::from("foo"), String::from("bar")); + let b = || { + let c = || { + //~^ ERROR: drop order + //~| NOTE: for more information, see + //~| HELP: add a dummy let to cause `tuple` to be fully captured + tuple.0; + //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` + }; + + c(); + }; + //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + + b(); +} fn main() { test1_all_need_migration(); @@ -140,4 +201,6 @@ fn main() { test5_drop_non_drop_aggregate_need_migration(); test6_significant_insignificant_drop_aggregate_need_migration(); test7_move_closures_non_copy_types_might_need_migration(); + test8_drop_order_and_blocks(); + test9_drop_order_and_nested_closures(); } diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr index ebf9f169fd4..b2b9ae8fd12 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr @@ -1,15 +1,24 @@ -error: drop order will change in Rust 2021 +error: changes to closure capture in Rust 2021 will affect drop order --> $DIR/significant_drop.rs:25:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -... | -LL | | let _t2 = t2.0; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +LL | +LL | let _t1 = t1.0; + | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` +LL | +LL | let _t2 = t2.0; + | ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0` +... +LL | } + | - + | | + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure + | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure | note: the lint level is defined here --> $DIR/significant_drop.rs:2:9 @@ -24,21 +33,26 @@ LL | LL | LL | LL | let _t = t.0; -LL | let _t1 = t1.0; +LL | ... -error: drop order will change in Rust 2021 - --> $DIR/significant_drop.rs:44:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -... | -LL | | let _t2 = t2; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:50:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +LL | +LL | let _t1 = t1.0; + | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0` +... +LL | } + | - + | | + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t`, `t1` to be fully captured @@ -48,21 +62,20 @@ LL | LL | LL | LL | let _t = t.0; -LL | let _t1 = t1.0; +LL | ... -error: drop order will change in Rust 2021 - --> $DIR/significant_drop.rs:61:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.0; -LL | | println!("{:?}", t1.1); -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:71:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured @@ -72,20 +85,20 @@ LL | LL | LL | LL | let _t = t.0; -LL | println!("{:?}", t1.1); +LL | ... -error: drop order will change in Rust 2021 - --> $DIR/significant_drop.rs:79:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.0; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:91:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured @@ -95,20 +108,20 @@ LL | LL | LL | LL | let _t = t.0; -LL | }; - | +LL | + ... -error: drop order will change in Rust 2021 - --> $DIR/significant_drop.rs:95:13 - | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.0; -LL | | }; - | |_____^ +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:109:13 + | +LL | let c = || { + | ^^ +... +LL | let _t = t.0; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured @@ -118,20 +131,20 @@ LL | LL | LL | LL | let _t = t.0; -LL | }; - | +LL | + ... -error: drop order will change in Rust 2021 - --> $DIR/significant_drop.rs:109:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:125:13 | -LL | let c = || { - | _____________^ -LL | | -LL | | -LL | | -LL | | let _t = t.1; -LL | | }; - | |_____^ +LL | let c = || { + | ^^ +... +LL | let _t = t.1; + | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` +... +LL | } + | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t` to be fully captured @@ -141,20 +154,25 @@ LL | LL | LL | LL | let _t = t.1; -LL | }; - | +LL | + ... -error: drop order will change in Rust 2021 - --> $DIR/significant_drop.rs:125:13 +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:143:13 | -LL | let c = move || { - | _____________^ -LL | | -LL | | -LL | | -LL | | println!("{:?} {:?}", t1.1, t.1); -LL | | }; - | |_____^ +LL | let c = move || { + | ^^^^^^^ +... +LL | println!("{:?} {:?}", t1.1, t.1); + | ---- --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1` + | | + | in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1` +... +LL | } + | - + | | + | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure + | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure | = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> help: add a dummy let to cause `t1`, `t` to be fully captured @@ -164,8 +182,54 @@ LL | LL | LL | LL | println!("{:?} {:?}", t1.1, t.1); +LL | + ... + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:163:21 + | +LL | let c = || { + | ^^ +... +LL | tuple.0; + | ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` +... +LL | } + | - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure + | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> +help: add a dummy let to cause `tuple` to be fully captured + | +LL | let c = || { let _ = &tuple; +LL | +LL | +LL | +LL | tuple.0; +LL | + ... + +error: changes to closure capture in Rust 2021 will affect drop order + --> $DIR/significant_drop.rs:181:17 + | +LL | let c = || { + | ^^ +... +LL | tuple.0; + | ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0` +... LL | }; + | - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure | + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html> +help: add a dummy let to cause `tuple` to be fully captured + | +LL | let c = || { let _ = &tuple; +LL | +LL | +LL | +LL | tuple.0; +LL | + ... -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors |
