diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 636e47b7ad2..4530df00c72 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -151,15 +151,13 @@ struct DropData { /// Whether this is a value Drop or a StorageDead. kind: DropKind, - - /// Whether this is a backwards-incompatible drop lint - backwards_incompatible_lint: bool, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub(crate) enum DropKind { Value, Storage, + ForLint, } #[derive(Debug)] @@ -248,7 +246,7 @@ impl Scope { /// use of optimizations in the MIR coroutine transform. fn needs_cleanup(&self) -> bool { self.drops.iter().any(|drop| match drop.kind { - DropKind::Value => true, + DropKind::Value | DropKind::ForLint => true, DropKind::Storage => false, }) } @@ -277,12 +275,8 @@ impl DropTree { // represents the block in the tree that should be jumped to once all // of the required drops have been performed. let fake_source_info = SourceInfo::outermost(DUMMY_SP); - let fake_data = DropData { - source_info: fake_source_info, - local: Local::MAX, - kind: DropKind::Storage, - backwards_incompatible_lint: false, - }; + let fake_data = + DropData { source_info: fake_source_info, local: Local::MAX, kind: DropKind::Storage }; let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]); Self { drops, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() } } @@ -411,6 +405,27 @@ impl DropTree { }; cfg.terminate(block, drop_node.data.source_info, terminator); } + DropKind::ForLint => { + let stmt = Statement { + source_info: drop_node.data.source_info, + kind: StatementKind::BackwardIncompatibleDropHint { + place: Box::new(drop_node.data.local.into()), + reason: BackwardIncompatibleDropReason::Edition2024, + }, + }; + cfg.push(block, stmt); + let target = blocks[drop_node.next].unwrap(); + if target != block { + // Diagnostics don't use this `Span` but debuginfo + // might. Since we don't want breakpoints to be placed + // here, especially when this is on an unwind path, we + // use `DUMMY_SP`. + let source_info = + SourceInfo { span: DUMMY_SP, ..drop_node.data.source_info }; + let terminator = TerminatorKind::Goto { target }; + cfg.terminate(block, source_info, terminator); + } + } // Root nodes don't correspond to a drop. DropKind::Storage if drop_idx == ROOT_NODE => {} DropKind::Storage => { @@ -770,12 +785,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local = place.as_local().unwrap_or_else(|| bug!("projection in tail call args")); - Some(DropData { - source_info, - local, - kind: DropKind::Value, - backwards_incompatible_lint: false, - }) + Some(DropData { source_info, local, kind: DropKind::Value }) } Operand::Constant(_) => None, }) @@ -822,6 +832,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); block = next; } + DropKind::ForLint => { + self.cfg.push(block, Statement { + source_info, + kind: StatementKind::BackwardIncompatibleDropHint { + place: Box::new(local.into()), + reason: BackwardIncompatibleDropReason::Edition2024, + }, + }); + } DropKind::Storage => { // Only temps and vars need their storage dead. assert!(local.index() > self.arg_count); @@ -1021,7 +1040,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { drop_kind: DropKind, ) { let needs_drop = match drop_kind { - DropKind::Value => { + DropKind::Value | DropKind::ForLint => { if !self.local_decls[local].ty.needs_drop(self.tcx, self.typing_env()) { return; } @@ -1101,7 +1120,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info: SourceInfo { span: scope_end, scope: scope.source_scope }, local, kind: drop_kind, - backwards_incompatible_lint: false, }); return; @@ -1135,8 +1153,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scope.drops.push(DropData { source_info: SourceInfo { span: scope_end, scope: scope.source_scope }, local, - kind: DropKind::Value, - backwards_incompatible_lint: true, + kind: DropKind::ForLint, }); return; @@ -1430,25 +1447,38 @@ fn build_scope_drops<'tcx>( continue; } - if drop_data.backwards_incompatible_lint { - cfg.push(block, Statement { - source_info, - kind: StatementKind::BackwardIncompatibleDropHint { - place: Box::new(local.into()), - reason: BackwardIncompatibleDropReason::Edition2024, - }, - }); - } else { - unwind_drops.add_entry_point(block, unwind_to); - let next = cfg.start_new_block(); - cfg.terminate(block, source_info, TerminatorKind::Drop { - place: local.into(), - target: next, - unwind: UnwindAction::Continue, - replace: false, - }); - block = next; + unwind_drops.add_entry_point(block, unwind_to); + let next = cfg.start_new_block(); + cfg.terminate(block, source_info, TerminatorKind::Drop { + place: local.into(), + target: next, + unwind: UnwindAction::Continue, + replace: false, + }); + block = next; + } + DropKind::ForLint => { + // If the operand has been moved, and we are not on an unwind + // path, then don't generate the drop. (We only take this into + // account for non-unwind paths so as not to disturb the + // caching mechanism.) + if scope.moved_locals.iter().any(|&o| o == local) { + continue; } + + if storage_dead_on_unwind { + debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local); + debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind); + unwind_to = unwind_drops.drops[unwind_to].next; + } + + cfg.push(block, Statement { + source_info, + kind: StatementKind::BackwardIncompatibleDropHint { + place: Box::new(local.into()), + reason: BackwardIncompatibleDropReason::Edition2024, + }, + }); } DropKind::Storage => { if storage_dead_on_unwind { @@ -1500,7 +1530,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { unwind_indices.push(unwind_indices[drop_node.next]); } } - DropKind::Value => { + DropKind::Value | DropKind::ForLint => { let unwind_drop = self .scopes .unwind_drops 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 index 54bedfdc0af..e9bbe30bd77 100644 --- 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 @@ -12,10 +12,9 @@ fn method_1(_1: Guard) -> () { let _8: OtherDrop; let _9: (); let mut _10: bool; - let mut _11: bool; + let mut _11: isize; let mut _12: isize; let mut _13: isize; - let mut _14: isize; scope 1 { debug other_drop => _8; } @@ -24,7 +23,6 @@ fn method_1(_1: Guard) -> () { } bb0: { - _11 = const false; _10 = const false; StorageLive(_2); StorageLive(_3); @@ -32,15 +30,14 @@ fn method_1(_1: Guard) -> () { StorageLive(_5); StorageLive(_6); _6 = &_1; - _5 = ::clone(move _6) -> [return: bb1, unwind: bb16]; + _5 = ::clone(move _6) -> [return: bb1, unwind: bb13]; } bb1: { - _11 = const true; StorageDead(_6); _4 = &_5; _3 = &(*_4); - _2 = method_2(move _3) -> [return: bb2, unwind: bb14]; + _2 = method_2(move _3) -> [return: bb2, unwind: bb12]; } bb2: { @@ -78,20 +75,19 @@ fn method_1(_1: Guard) -> () { bb7: { backward incompatible drop(_2); backward incompatible drop(_5); - goto -> bb24; + goto -> bb21; } bb8: { - drop(_5) -> [return: bb9, unwind: bb16]; + drop(_5) -> [return: bb9, unwind: bb13]; } bb9: { - _11 = const false; StorageDead(_5); StorageDead(_4); _10 = const false; StorageDead(_2); - drop(_1) -> [return: bb10, unwind: bb17]; + drop(_1) -> [return: bb10, unwind: bb14]; } bb10: { @@ -99,7 +95,7 @@ fn method_1(_1: Guard) -> () { } bb11 (cleanup): { - goto -> bb28; + goto -> bb25; } bb12 (cleanup): { @@ -107,77 +103,57 @@ fn method_1(_1: Guard) -> () { } bb13 (cleanup): { - goto -> bb15; + drop(_1) -> [return: bb14, unwind terminate(cleanup)]; } bb14 (cleanup): { - drop(_5) -> [return: bb15, unwind terminate(cleanup)]; - } - - bb15 (cleanup): { - goto -> bb30; - } - - bb16 (cleanup): { - drop(_1) -> [return: bb17, unwind terminate(cleanup)]; - } - - bb17 (cleanup): { resume; } - bb18: { + bb15: { goto -> bb8; } - bb19 (cleanup): { + bb16 (cleanup): { + goto -> bb12; + } + + bb17 (cleanup): { + goto -> bb12; + } + + bb18: { + goto -> bb15; + } + + bb19: { goto -> bb15; } bb20 (cleanup): { - goto -> bb15; + goto -> bb12; } bb21: { - goto -> bb18; + _11 = discriminant(_2); + switchInt(move _11) -> [0: bb18, otherwise: bb19]; } - bb22: { - goto -> bb18; + bb22 (cleanup): { + _12 = discriminant(_2); + switchInt(move _12) -> [0: bb16, otherwise: bb20]; } bb23 (cleanup): { - goto -> bb15; + goto -> bb12; } - bb24: { - _12 = discriminant(_2); - switchInt(move _12) -> [0: bb21, otherwise: bb22]; + bb24 (cleanup): { + goto -> bb12; } bb25 (cleanup): { _13 = discriminant(_2); - switchInt(move _13) -> [0: bb19, otherwise: bb23]; - } - - bb26 (cleanup): { - goto -> bb12; - } - - bb27 (cleanup): { - goto -> bb12; - } - - bb28 (cleanup): { - _14 = discriminant(_2); - switchInt(move _14) -> [0: bb26, otherwise: bb27]; - } - - bb29 (cleanup): { - drop(_5) -> [return: bb16, unwind terminate(cleanup)]; - } - - bb30 (cleanup): { - switchInt(copy _11) -> [0: bb16, otherwise: bb29]; + 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 index 54bedfdc0af..e9bbe30bd77 100644 --- 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 @@ -12,10 +12,9 @@ fn method_1(_1: Guard) -> () { let _8: OtherDrop; let _9: (); let mut _10: bool; - let mut _11: bool; + let mut _11: isize; let mut _12: isize; let mut _13: isize; - let mut _14: isize; scope 1 { debug other_drop => _8; } @@ -24,7 +23,6 @@ fn method_1(_1: Guard) -> () { } bb0: { - _11 = const false; _10 = const false; StorageLive(_2); StorageLive(_3); @@ -32,15 +30,14 @@ fn method_1(_1: Guard) -> () { StorageLive(_5); StorageLive(_6); _6 = &_1; - _5 = ::clone(move _6) -> [return: bb1, unwind: bb16]; + _5 = ::clone(move _6) -> [return: bb1, unwind: bb13]; } bb1: { - _11 = const true; StorageDead(_6); _4 = &_5; _3 = &(*_4); - _2 = method_2(move _3) -> [return: bb2, unwind: bb14]; + _2 = method_2(move _3) -> [return: bb2, unwind: bb12]; } bb2: { @@ -78,20 +75,19 @@ fn method_1(_1: Guard) -> () { bb7: { backward incompatible drop(_2); backward incompatible drop(_5); - goto -> bb24; + goto -> bb21; } bb8: { - drop(_5) -> [return: bb9, unwind: bb16]; + drop(_5) -> [return: bb9, unwind: bb13]; } bb9: { - _11 = const false; StorageDead(_5); StorageDead(_4); _10 = const false; StorageDead(_2); - drop(_1) -> [return: bb10, unwind: bb17]; + drop(_1) -> [return: bb10, unwind: bb14]; } bb10: { @@ -99,7 +95,7 @@ fn method_1(_1: Guard) -> () { } bb11 (cleanup): { - goto -> bb28; + goto -> bb25; } bb12 (cleanup): { @@ -107,77 +103,57 @@ fn method_1(_1: Guard) -> () { } bb13 (cleanup): { - goto -> bb15; + drop(_1) -> [return: bb14, unwind terminate(cleanup)]; } bb14 (cleanup): { - drop(_5) -> [return: bb15, unwind terminate(cleanup)]; - } - - bb15 (cleanup): { - goto -> bb30; - } - - bb16 (cleanup): { - drop(_1) -> [return: bb17, unwind terminate(cleanup)]; - } - - bb17 (cleanup): { resume; } - bb18: { + bb15: { goto -> bb8; } - bb19 (cleanup): { + bb16 (cleanup): { + goto -> bb12; + } + + bb17 (cleanup): { + goto -> bb12; + } + + bb18: { + goto -> bb15; + } + + bb19: { goto -> bb15; } bb20 (cleanup): { - goto -> bb15; + goto -> bb12; } bb21: { - goto -> bb18; + _11 = discriminant(_2); + switchInt(move _11) -> [0: bb18, otherwise: bb19]; } - bb22: { - goto -> bb18; + bb22 (cleanup): { + _12 = discriminant(_2); + switchInt(move _12) -> [0: bb16, otherwise: bb20]; } bb23 (cleanup): { - goto -> bb15; + goto -> bb12; } - bb24: { - _12 = discriminant(_2); - switchInt(move _12) -> [0: bb21, otherwise: bb22]; + bb24 (cleanup): { + goto -> bb12; } bb25 (cleanup): { _13 = discriminant(_2); - switchInt(move _13) -> [0: bb19, otherwise: bb23]; - } - - bb26 (cleanup): { - goto -> bb12; - } - - bb27 (cleanup): { - goto -> bb12; - } - - bb28 (cleanup): { - _14 = discriminant(_2); - switchInt(move _14) -> [0: bb26, otherwise: bb27]; - } - - bb29 (cleanup): { - drop(_5) -> [return: bb16, unwind terminate(cleanup)]; - } - - bb30 (cleanup): { - switchInt(copy _11) -> [0: bb16, otherwise: bb29]; + 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 index b67b3580875..065e08c3409 100644 --- a/tests/mir-opt/tail_expr_drop_order_unwind.rs +++ b/tests/mir-opt/tail_expr_drop_order_unwind.rs @@ -26,8 +26,8 @@ fn method_1(g: Guard) { match method_2(&g.clone()) { Ok(other_drop) => { // repro needs something else being dropped too. - }, - Err(err) => {}, + } + Err(err) => {} } }