1
Fork 0

Add note pointing to where a closure and it's captured variables are dropped

This commit is contained in:
Roxane 2021-07-07 10:29:06 -04:00
parent 0e8e89daa6
commit 2900c1a5e8
20 changed files with 373 additions and 30 deletions

View file

@ -511,6 +511,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.as_str(),
);
for (var_hir_id, diagnostics_info) in need_migrations.iter() {
let mut captured_names = format!("");
for (captured_hir_id, captured_name) in diagnostics_info.iter() {
if let Some(captured_hir_id) = captured_hir_id {
let cause_span = self.tcx.hir().span(*captured_hir_id);
@ -518,8 +519,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.hir().name(*var_hir_id),
captured_name,
));
if captured_names == "" {
captured_names = format!("`{}`", captured_name);
} else {
captured_names = format!("{}, `{}`", captured_names, captured_name);
}
}
}
if reasons.contains("drop order") {
let drop_location_span = drop_location_span(self.tcx, &closure_hir_id);
diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` would be dropped here, but in Rust 2021, only {} would be dropped here alongside the closure",
self.tcx.hir().name(*var_hir_id),
captured_names,
));
}
}
diagnostics_builder.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
let closure_body_span = self.tcx.hir().span(body_id.hir_id);
@ -1350,6 +1365,31 @@ fn apply_capture_kind_on_capture_ty(
}
}
/// Returns the Span of where the value with the provided HirId would be dropped
fn drop_location_span(tcx: TyCtxt<'tcx>, hir_id: &hir::HirId) -> Span {
let owner_id = tcx.hir().get_enclosing_scope(*hir_id).unwrap();
let owner_node = tcx.hir().get(owner_id);
match owner_node {
hir::Node::Item(item) => match item.kind {
hir::ItemKind::Fn(_, _, owner_id) => {
let owner_span = tcx.hir().span(owner_id.hir_id);
tcx.sess.source_map().end_point(owner_span)
}
_ => {
bug!("Drop location span error: need to handle more ItemKind {:?}", item.kind);
}
},
hir::Node::Block(block) => {
let owner_span = tcx.hir().span(block.hir_id);
tcx.sess.source_map().end_point(owner_span)
}
_ => {
bug!("Drop location span error: need to handle more Node {:?}", owner_node);
}
}
}
struct InferBorrowKind<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>,

View file

@ -1,5 +1,6 @@
// run-rustfix
#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
use std::thread;
@ -12,8 +13,10 @@ fn test_send_trait() {
let fptr = SendPointer(&mut f as *mut i32);
thread::spawn(move || { let _ = &fptr; unsafe {
//~^ ERROR: `Send` closure trait implementation
//~| 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`
} });
}
@ -29,8 +32,10 @@ fn test_sync_trait() {
let fptr = SyncPointer(f);
thread::spawn(move || { let _ = &fptr; unsafe {
//~^ ERROR: `Sync`, `Send` closure trait implementation
//~| 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`
} });
}
@ -50,8 +55,10 @@ fn test_clone_trait() {
let f = U(S(String::from("Hello World")), T(0));
let c = || { let _ = &f;
//~^ ERROR: `Clone` closure trait implementation, and drop order
//~| 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 +66,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();

View file

@ -1,5 +1,6 @@
// run-rustfix
#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
use std::thread;
@ -12,8 +13,10 @@ fn test_send_trait() {
let fptr = SendPointer(&mut f as *mut i32);
thread::spawn(move || unsafe {
//~^ ERROR: `Send` closure trait implementation
//~| 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`
});
}
@ -29,8 +32,10 @@ fn test_sync_trait() {
let fptr = SyncPointer(f);
thread::spawn(move || unsafe {
//~^ ERROR: `Sync`, `Send` closure trait implementation
//~| 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`
});
}
@ -50,8 +55,10 @@ fn test_clone_trait() {
let f = U(S(String::from("Hello World")), T(0));
let c = || {
//~^ ERROR: `Clone` closure trait implementation, and drop order
//~| 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 +66,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();

View file

@ -1,12 +1,14 @@
error: changes to closure capture in Rust 2021 will affect `Send` closure trait implementation
--> $DIR/auto_traits.rs:13:19
--> $DIR/auto_traits.rs:14:19
|
LL | thread::spawn(move || unsafe {
| ___________________^
LL | |
LL | |
LL | |
LL | | *fptr.0 = 20;
| | ------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
LL | |
LL | | });
| |_____^
|
@ -21,19 +23,22 @@ help: add a dummy let to cause `fptr` to be fully captured
LL | thread::spawn(move || { let _ = &fptr; unsafe {
LL |
LL |
LL |
LL | *fptr.0 = 20;
LL | } });
|
LL |
...
error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` closure trait implementation
--> $DIR/auto_traits.rs:30:19
--> $DIR/auto_traits.rs:33:19
|
LL | thread::spawn(move || unsafe {
| ___________________^
LL | |
LL | |
LL | |
LL | | *fptr.0.0 = 20;
| | --------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
LL | |
LL | | });
| |_____^
|
@ -43,22 +48,28 @@ help: add a dummy let to cause `fptr` to be fully captured
LL | thread::spawn(move || { let _ = &fptr; unsafe {
LL |
LL |
LL |
LL | *fptr.0.0 = 20;
LL | } });
|
LL |
...
error: changes to closure capture in Rust 2021 will affect `Clone` closure trait implementation, and drop order
--> $DIR/auto_traits.rs:51:13
--> $DIR/auto_traits.rs:56:13
|
LL | let c = || {
| _____________^
LL | |
LL | |
LL | |
LL | | let f_1 = f.1;
| | --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
LL | |
LL | | println!("{:?}", f_1.0);
LL | | };
| |_____^
...
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
@ -66,10 +77,10 @@ help: add a dummy let to cause `f` to be fully captured
LL | let c = || { let _ = &f;
LL |
LL |
LL |
LL | let f_1 = f.1;
LL | println!("{:?}", f_1.0);
LL | };
|
LL |
...
error: aborting due to 3 previous errors

View file

@ -27,6 +27,9 @@ fn test1_all_need_migration() {
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
@ -48,6 +51,8 @@ fn test2_only_precise_paths_need_migration() {
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.
@ -65,6 +70,7 @@ fn test3_only_by_value_need_migration() {
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.
@ -85,6 +91,7 @@ fn test4_only_non_copy_types_need_migration() {
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);
@ -105,6 +112,7 @@ fn test5_only_drop_types_need_migration() {
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.
@ -122,6 +130,8 @@ fn test6_move_closures_non_copy_types_might_need_migration() {
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,
@ -139,6 +149,7 @@ fn test7_drop_non_drop_aggregate_need_migration() {
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();

View file

@ -27,6 +27,9 @@ fn test1_all_need_migration() {
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
@ -48,6 +51,8 @@ fn test2_only_precise_paths_need_migration() {
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.
@ -65,6 +70,7 @@ fn test3_only_by_value_need_migration() {
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.
@ -85,6 +91,7 @@ fn test4_only_non_copy_types_need_migration() {
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);
@ -105,6 +112,7 @@ fn test5_only_drop_types_need_migration() {
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.
@ -122,6 +130,8 @@ fn test6_move_closures_non_copy_types_might_need_migration() {
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,
@ -139,6 +149,7 @@ fn test7_drop_non_drop_aggregate_need_migration() {
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();

View file

@ -18,6 +18,13 @@ LL | | let _t2 = t2.0;
LL | |
LL | | };
| |_____^
...
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
@ -36,7 +43,7 @@ LL | let _t = t.0;
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/insignificant_drop.rs:38:13
--> $DIR/insignificant_drop.rs:41:13
|
LL | let c = || {
| _____________^
@ -52,6 +59,12 @@ LL | |
LL | | let _t2 = t2;
LL | | };
| |_____^
...
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
@ -65,7 +78,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/insignificant_drop.rs:57:13
--> $DIR/insignificant_drop.rs:62:13
|
LL | let c = || {
| _____________^
@ -78,6 +91,9 @@ LL | |
LL | | println!("{}", t1.1);
LL | | };
| |_____^
...
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
@ -91,7 +107,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/insignificant_drop.rs:77:13
--> $DIR/insignificant_drop.rs:83:13
|
LL | let c = || {
| _____________^
@ -104,6 +120,9 @@ LL | |
LL | | let _t1 = t1.0;
LL | | };
| |_____^
...
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
@ -117,7 +136,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/insignificant_drop.rs:97:13
--> $DIR/insignificant_drop.rs:104:13
|
LL | let c = || {
| _____________^
@ -130,6 +149,9 @@ LL | |
LL | | let _s = s.0;
LL | | };
| |_____^
...
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
@ -143,7 +165,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/insignificant_drop.rs:114:13
--> $DIR/insignificant_drop.rs:122:13
|
LL | let c = move || {
| _____________^
@ -158,6 +180,12 @@ LL | |
LL | |
LL | | };
| |_____^
...
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
@ -171,7 +199,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/insignificant_drop.rs:132:13
--> $DIR/insignificant_drop.rs:142:13
|
LL | let c = || {
| _____________^
@ -183,6 +211,9 @@ LL | | let _t = t.0;
LL | |
LL | | };
| |_____^
...
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

View file

@ -44,6 +44,7 @@ fn significant_drop_needs_migration() {
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
@ -63,6 +64,7 @@ fn generic_struct_with_significant_drop_needs_migration() {
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();

View file

@ -44,6 +44,7 @@ fn significant_drop_needs_migration() {
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
@ -63,6 +64,7 @@ fn generic_struct_with_significant_drop_needs_migration() {
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();

View file

@ -11,6 +11,9 @@ LL | | let _t = t.0;
LL | |
LL | | };
| |_____^
...
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
@ -29,7 +32,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/insignificant_drop_attr_migrations.rs:56:13
--> $DIR/insignificant_drop_attr_migrations.rs:57:13
|
LL | let c = move || {
| _____________^
@ -41,6 +44,9 @@ LL | | let _t = t.1;
LL | |
LL | | };
| |_____^
...
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

View file

@ -22,11 +22,11 @@ fn closure_contains_block() {
//~| 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));
@ -38,6 +38,7 @@ fn closure_doesnt_contain_block() {
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();

View file

@ -22,11 +22,11 @@ fn closure_contains_block() {
//~| 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));
@ -38,6 +38,7 @@ fn closure_doesnt_contain_block() {
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();

View file

@ -9,9 +9,11 @@ LL | |
LL | | let _t = t.0;
| | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
LL | |
LL | |
LL | | };
| |_____^
...
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
@ -36,6 +38,9 @@ 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

View file

@ -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)]
@ -18,8 +19,10 @@ where
let f = panic::AssertUnwindSafe(f);
let result = panic::catch_unwind(move || { let _ = &f;
//~^ ERROR: `UnwindSafe`, `RefUnwindSafe` closure trait implementation
//~| 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");

View file

@ -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)]
@ -18,8 +19,10 @@ where
let f = panic::AssertUnwindSafe(f);
let result = panic::catch_unwind(move || {
//~^ ERROR: `UnwindSafe`, `RefUnwindSafe` closure trait implementation
//~| 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");

View file

@ -1,12 +1,14 @@
error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnwindSafe` closure trait implementation
--> $DIR/mir_calls_to_shims.rs:19:38
--> $DIR/mir_calls_to_shims.rs:20:38
|
LL | let result = panic::catch_unwind(move || {
| ______________________________________^
LL | |
LL | |
LL | |
LL | | f.0()
| | --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
LL | |
LL | | });
| |_____^
|
@ -21,9 +23,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 | f.0()
LL | });
|
LL |
...
error: aborting due to previous error

View file

@ -10,6 +10,9 @@ LL | | let _t = t.0;
LL | | let _t = &t.1;
LL | | };
| |_____^
...
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
@ -42,6 +45,9 @@ 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 | | };
| |_____^
...
LL | }
| - in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1`, `u.0.0`, `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

View file

@ -36,6 +36,9 @@ fn test1_all_need_migration() {
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
@ -57,6 +60,8 @@ fn test2_only_precise_paths_need_migration() {
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.
@ -74,6 +79,7 @@ fn test3_only_by_value_need_migration() {
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.
@ -92,6 +98,7 @@ fn test4_type_contains_drop_need_migration() {
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,
@ -109,6 +116,7 @@ fn test5_drop_non_drop_aggregate_need_migration() {
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() {
@ -124,6 +132,7 @@ fn test6_significant_insignificant_drop_aggregate_need_migration() {
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.
@ -142,6 +151,47 @@ fn test7_move_closures_non_copy_types_might_need_migration() {
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();
@ -151,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();
}

View file

@ -36,6 +36,9 @@ fn test1_all_need_migration() {
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
@ -57,6 +60,8 @@ fn test2_only_precise_paths_need_migration() {
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.
@ -74,6 +79,7 @@ fn test3_only_by_value_need_migration() {
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.
@ -92,6 +98,7 @@ fn test4_type_contains_drop_need_migration() {
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,
@ -109,6 +116,7 @@ fn test5_drop_non_drop_aggregate_need_migration() {
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() {
@ -124,6 +132,7 @@ fn test6_significant_insignificant_drop_aggregate_need_migration() {
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.
@ -142,6 +151,47 @@ fn test7_move_closures_non_copy_types_might_need_migration() {
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();
@ -151,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();
}

View file

@ -17,6 +17,13 @@ LL | | let _t2 = t2.0;
LL | |
LL | | };
| |_____^
...
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
@ -35,7 +42,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/significant_drop.rs:47:13
--> $DIR/significant_drop.rs:50:13
|
LL | let c = || {
| _____________^
@ -51,6 +58,12 @@ LL | |
LL | | let _t2 = t2;
LL | | };
| |_____^
...
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
@ -64,7 +77,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/significant_drop.rs:66:13
--> $DIR/significant_drop.rs:71:13
|
LL | let c = || {
| _____________^
@ -77,6 +90,9 @@ LL | |
LL | | println!("{:?}", t1.1);
LL | | };
| |_____^
...
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
@ -90,7 +106,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/significant_drop.rs:85:13
--> $DIR/significant_drop.rs:91:13
|
LL | let c = || {
| _____________^
@ -102,6 +118,9 @@ LL | | let _t = t.0;
LL | |
LL | | };
| |_____^
...
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
@ -115,7 +134,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/significant_drop.rs:102:13
--> $DIR/significant_drop.rs:109:13
|
LL | let c = || {
| _____________^
@ -127,6 +146,9 @@ LL | | let _t = t.0;
LL | |
LL | | };
| |_____^
...
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
@ -140,7 +162,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/significant_drop.rs:117:13
--> $DIR/significant_drop.rs:125:13
|
LL | let c = || {
| _____________^
@ -152,6 +174,9 @@ LL | | let _t = t.1;
LL | |
LL | | };
| |_____^
...
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
@ -165,7 +190,7 @@ LL |
...
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/significant_drop.rs:134:13
--> $DIR/significant_drop.rs:143:13
|
LL | let c = move || {
| _____________^
@ -180,6 +205,12 @@ LL | |
LL | |
LL | | };
| |_____^
...
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
@ -192,5 +223,61 @@ LL | println!("{:?} {:?}", t1.1, t.1);
LL |
...
error: aborting due to 7 previous errors
error: changes to closure capture in Rust 2021 will affect drop order
--> $DIR/significant_drop.rs:163:21
|
LL | let c = || {
| _____________________^
LL | |
LL | |
LL | |
LL | | tuple.0;
| | ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
LL | |
LL | | };
| |_____________^
...
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 | |
LL | |
LL | |
LL | | tuple.0;
| | ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
LL | |
LL | | };
| |_________^
...
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 9 previous errors