diff options
| author | bors <bors@rust-lang.org> | 2024-12-19 15:58:08 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-12-19 15:58:08 +0000 |
| commit | 11663cd3bfefef7d34e8f0892c250bf698049392 (patch) | |
| tree | 3a438acdc61750d33e92eb7402e8f0dccd0f441b /tests | |
| parent | 3bf62ccc1055a94dfa6a72650b10a71dcf232429 (diff) | |
| parent | 6564403641afde8bf445914ec2996fe7219289ab (diff) | |
Auto merge of #134486 - compiler-errors:drop-for-lint, r=nikomatsakis
Make sure we handle `backwards_incompatible_lint` drops appropriately in drop elaboration In #131326, a new kind of scheduled drop (`drop_kind: DropKind::Value` + `backwards_incompatible_lint: true`) was added so that we could insert a new kind of no-op MIR statement (`backward incompatible drop`) for linting purposes. These drops were intended to have *no side-effects*, but drop elaboration code forgot to handle these drops specially and they were handled otherwise as normal drops in most of the code. This ends up being **unsound** since we insert more than one drop call for some values, which means that `Drop::drop` could be called more than once. This PR fixes this by splitting out the `DropKind::ForLint` and adjusting the code. I'm not totally certain if all of the places I've adjusted are either reachable or correct, but I'm pretty certain that it's *more* correct than it was previously. cc `@dingxiangfei2009` r? nikomatsakis Fixes #134482
Diffstat (limited to 'tests')
3 files changed, 354 insertions, 0 deletions
diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir new file mode 100644 index 00000000000..e9bbe30bd77 --- /dev/null +++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-abort.mir @@ -0,0 +1,159 @@ +// MIR for `method_1` after ElaborateDrops + +fn method_1(_1: Guard) -> () { + debug g => _1; + let mut _0: (); + let mut _2: std::result::Result<OtherDrop, ()>; + let mut _3: &Guard; + let _4: &Guard; + let _5: Guard; + let mut _6: &Guard; + let mut _7: isize; + let _8: OtherDrop; + let _9: (); + let mut _10: bool; + let mut _11: isize; + let mut _12: isize; + let mut _13: isize; + scope 1 { + debug other_drop => _8; + } + scope 2 { + debug err => _9; + } + + bb0: { + _10 = const false; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + _6 = &_1; + _5 = <Guard as Clone>::clone(move _6) -> [return: bb1, unwind: bb13]; + } + + bb1: { + StorageDead(_6); + _4 = &_5; + _3 = &(*_4); + _2 = method_2(move _3) -> [return: bb2, unwind: bb12]; + } + + bb2: { + _10 = const true; + StorageDead(_3); + PlaceMention(_2); + _7 = discriminant(_2); + switchInt(move _7) -> [0: bb5, 1: bb4, otherwise: bb3]; + } + + bb3: { + unreachable; + } + + bb4: { + StorageLive(_9); + _9 = copy ((_2 as Err).0: ()); + _0 = const (); + StorageDead(_9); + goto -> bb7; + } + + bb5: { + StorageLive(_8); + _8 = move ((_2 as Ok).0: OtherDrop); + _0 = const (); + drop(_8) -> [return: bb6, unwind: bb11]; + } + + bb6: { + StorageDead(_8); + goto -> bb7; + } + + bb7: { + backward incompatible drop(_2); + backward incompatible drop(_5); + goto -> bb21; + } + + bb8: { + drop(_5) -> [return: bb9, unwind: bb13]; + } + + bb9: { + StorageDead(_5); + StorageDead(_4); + _10 = const false; + StorageDead(_2); + drop(_1) -> [return: bb10, unwind: bb14]; + } + + bb10: { + return; + } + + bb11 (cleanup): { + goto -> bb25; + } + + bb12 (cleanup): { + drop(_5) -> [return: bb13, unwind terminate(cleanup)]; + } + + bb13 (cleanup): { + drop(_1) -> [return: bb14, unwind terminate(cleanup)]; + } + + bb14 (cleanup): { + resume; + } + + bb15: { + goto -> bb8; + } + + bb16 (cleanup): { + goto -> bb12; + } + + bb17 (cleanup): { + goto -> bb12; + } + + bb18: { + goto -> bb15; + } + + bb19: { + goto -> bb15; + } + + bb20 (cleanup): { + goto -> bb12; + } + + bb21: { + _11 = discriminant(_2); + switchInt(move _11) -> [0: bb18, otherwise: bb19]; + } + + bb22 (cleanup): { + _12 = discriminant(_2); + switchInt(move _12) -> [0: bb16, otherwise: bb20]; + } + + bb23 (cleanup): { + goto -> bb12; + } + + bb24 (cleanup): { + goto -> bb12; + } + + bb25 (cleanup): { + _13 = discriminant(_2); + switchInt(move _13) -> [0: bb23, otherwise: bb24]; + } +} diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir new file mode 100644 index 00000000000..e9bbe30bd77 --- /dev/null +++ b/tests/mir-opt/tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.panic-unwind.mir @@ -0,0 +1,159 @@ +// MIR for `method_1` after ElaborateDrops + +fn method_1(_1: Guard) -> () { + debug g => _1; + let mut _0: (); + let mut _2: std::result::Result<OtherDrop, ()>; + let mut _3: &Guard; + let _4: &Guard; + let _5: Guard; + let mut _6: &Guard; + let mut _7: isize; + let _8: OtherDrop; + let _9: (); + let mut _10: bool; + let mut _11: isize; + let mut _12: isize; + let mut _13: isize; + scope 1 { + debug other_drop => _8; + } + scope 2 { + debug err => _9; + } + + bb0: { + _10 = const false; + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + _6 = &_1; + _5 = <Guard as Clone>::clone(move _6) -> [return: bb1, unwind: bb13]; + } + + bb1: { + StorageDead(_6); + _4 = &_5; + _3 = &(*_4); + _2 = method_2(move _3) -> [return: bb2, unwind: bb12]; + } + + bb2: { + _10 = const true; + StorageDead(_3); + PlaceMention(_2); + _7 = discriminant(_2); + switchInt(move _7) -> [0: bb5, 1: bb4, otherwise: bb3]; + } + + bb3: { + unreachable; + } + + bb4: { + StorageLive(_9); + _9 = copy ((_2 as Err).0: ()); + _0 = const (); + StorageDead(_9); + goto -> bb7; + } + + bb5: { + StorageLive(_8); + _8 = move ((_2 as Ok).0: OtherDrop); + _0 = const (); + drop(_8) -> [return: bb6, unwind: bb11]; + } + + bb6: { + StorageDead(_8); + goto -> bb7; + } + + bb7: { + backward incompatible drop(_2); + backward incompatible drop(_5); + goto -> bb21; + } + + bb8: { + drop(_5) -> [return: bb9, unwind: bb13]; + } + + bb9: { + StorageDead(_5); + StorageDead(_4); + _10 = const false; + StorageDead(_2); + drop(_1) -> [return: bb10, unwind: bb14]; + } + + bb10: { + return; + } + + bb11 (cleanup): { + goto -> bb25; + } + + bb12 (cleanup): { + drop(_5) -> [return: bb13, unwind terminate(cleanup)]; + } + + bb13 (cleanup): { + drop(_1) -> [return: bb14, unwind terminate(cleanup)]; + } + + bb14 (cleanup): { + resume; + } + + bb15: { + goto -> bb8; + } + + bb16 (cleanup): { + goto -> bb12; + } + + bb17 (cleanup): { + goto -> bb12; + } + + bb18: { + goto -> bb15; + } + + bb19: { + goto -> bb15; + } + + bb20 (cleanup): { + goto -> bb12; + } + + bb21: { + _11 = discriminant(_2); + switchInt(move _11) -> [0: bb18, otherwise: bb19]; + } + + bb22 (cleanup): { + _12 = discriminant(_2); + switchInt(move _12) -> [0: bb16, otherwise: bb20]; + } + + bb23 (cleanup): { + goto -> bb12; + } + + bb24 (cleanup): { + goto -> bb12; + } + + bb25 (cleanup): { + _13 = discriminant(_2); + switchInt(move _13) -> [0: bb23, otherwise: bb24]; + } +} diff --git a/tests/mir-opt/tail_expr_drop_order_unwind.rs b/tests/mir-opt/tail_expr_drop_order_unwind.rs new file mode 100644 index 00000000000..065e08c3409 --- /dev/null +++ b/tests/mir-opt/tail_expr_drop_order_unwind.rs @@ -0,0 +1,36 @@ +// skip-filecheck +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// EMIT_MIR tail_expr_drop_order_unwind.method_1.ElaborateDrops.after.mir + +#![deny(tail_expr_drop_order)] + +use std::backtrace::Backtrace; + +#[derive(Clone)] +struct Guard; +impl Drop for Guard { + fn drop(&mut self) { + println!("Drop!"); + } +} + +#[derive(Clone)] +struct OtherDrop; +impl Drop for OtherDrop { + fn drop(&mut self) { + println!("Drop!"); + } +} + +fn method_1(g: Guard) { + match method_2(&g.clone()) { + Ok(other_drop) => { + // repro needs something else being dropped too. + } + Err(err) => {} + } +} + +fn method_2(_: &Guard) -> Result<OtherDrop, ()> { + panic!("Method 2 panics!"); +} |
