Separate DropKind::ForLint

This commit is contained in:
Michael Goulet 2024-12-18 21:57:20 +00:00
parent 2e57394d80
commit 5e079011ea
4 changed files with 135 additions and 153 deletions

View file

@ -151,15 +151,13 @@ struct DropData {
/// Whether this is a value Drop or a StorageDead. /// Whether this is a value Drop or a StorageDead.
kind: DropKind, kind: DropKind,
/// Whether this is a backwards-incompatible drop lint
backwards_incompatible_lint: bool,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum DropKind { pub(crate) enum DropKind {
Value, Value,
Storage, Storage,
ForLint,
} }
#[derive(Debug)] #[derive(Debug)]
@ -248,7 +246,7 @@ impl Scope {
/// use of optimizations in the MIR coroutine transform. /// use of optimizations in the MIR coroutine transform.
fn needs_cleanup(&self) -> bool { fn needs_cleanup(&self) -> bool {
self.drops.iter().any(|drop| match drop.kind { self.drops.iter().any(|drop| match drop.kind {
DropKind::Value => true, DropKind::Value | DropKind::ForLint => true,
DropKind::Storage => false, DropKind::Storage => false,
}) })
} }
@ -277,12 +275,8 @@ impl DropTree {
// represents the block in the tree that should be jumped to once all // represents the block in the tree that should be jumped to once all
// of the required drops have been performed. // of the required drops have been performed.
let fake_source_info = SourceInfo::outermost(DUMMY_SP); let fake_source_info = SourceInfo::outermost(DUMMY_SP);
let fake_data = DropData { let fake_data =
source_info: fake_source_info, DropData { source_info: fake_source_info, local: Local::MAX, kind: DropKind::Storage };
local: Local::MAX,
kind: DropKind::Storage,
backwards_incompatible_lint: false,
};
let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]); let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]);
Self { drops, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() } 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); 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. // Root nodes don't correspond to a drop.
DropKind::Storage if drop_idx == ROOT_NODE => {} DropKind::Storage if drop_idx == ROOT_NODE => {}
DropKind::Storage => { DropKind::Storage => {
@ -770,12 +785,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let local = let local =
place.as_local().unwrap_or_else(|| bug!("projection in tail call args")); place.as_local().unwrap_or_else(|| bug!("projection in tail call args"));
Some(DropData { Some(DropData { source_info, local, kind: DropKind::Value })
source_info,
local,
kind: DropKind::Value,
backwards_incompatible_lint: false,
})
} }
Operand::Constant(_) => None, Operand::Constant(_) => None,
}) })
@ -822,6 +832,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}); });
block = next; block = next;
} }
DropKind::ForLint => {
self.cfg.push(block, Statement {
source_info,
kind: StatementKind::BackwardIncompatibleDropHint {
place: Box::new(local.into()),
reason: BackwardIncompatibleDropReason::Edition2024,
},
});
}
DropKind::Storage => { DropKind::Storage => {
// Only temps and vars need their storage dead. // Only temps and vars need their storage dead.
assert!(local.index() > self.arg_count); assert!(local.index() > self.arg_count);
@ -1021,7 +1040,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
drop_kind: DropKind, drop_kind: DropKind,
) { ) {
let needs_drop = match drop_kind { 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()) { if !self.local_decls[local].ty.needs_drop(self.tcx, self.typing_env()) {
return; return;
} }
@ -1101,7 +1120,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
source_info: SourceInfo { span: scope_end, scope: scope.source_scope }, source_info: SourceInfo { span: scope_end, scope: scope.source_scope },
local, local,
kind: drop_kind, kind: drop_kind,
backwards_incompatible_lint: false,
}); });
return; return;
@ -1135,8 +1153,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
scope.drops.push(DropData { scope.drops.push(DropData {
source_info: SourceInfo { span: scope_end, scope: scope.source_scope }, source_info: SourceInfo { span: scope_end, scope: scope.source_scope },
local, local,
kind: DropKind::Value, kind: DropKind::ForLint,
backwards_incompatible_lint: true,
}); });
return; return;
@ -1430,25 +1447,38 @@ fn build_scope_drops<'tcx>(
continue; continue;
} }
if drop_data.backwards_incompatible_lint { unwind_drops.add_entry_point(block, unwind_to);
cfg.push(block, Statement { let next = cfg.start_new_block();
source_info, cfg.terminate(block, source_info, TerminatorKind::Drop {
kind: StatementKind::BackwardIncompatibleDropHint { place: local.into(),
place: Box::new(local.into()), target: next,
reason: BackwardIncompatibleDropReason::Edition2024, unwind: UnwindAction::Continue,
}, replace: false,
}); });
} else { block = next;
unwind_drops.add_entry_point(block, unwind_to); }
let next = cfg.start_new_block(); DropKind::ForLint => {
cfg.terminate(block, source_info, TerminatorKind::Drop { // If the operand has been moved, and we are not on an unwind
place: local.into(), // path, then don't generate the drop. (We only take this into
target: next, // account for non-unwind paths so as not to disturb the
unwind: UnwindAction::Continue, // caching mechanism.)
replace: false, if scope.moved_locals.iter().any(|&o| o == local) {
}); continue;
block = next;
} }
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 => { DropKind::Storage => {
if storage_dead_on_unwind { if storage_dead_on_unwind {
@ -1500,7 +1530,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
unwind_indices.push(unwind_indices[drop_node.next]); unwind_indices.push(unwind_indices[drop_node.next]);
} }
} }
DropKind::Value => { DropKind::Value | DropKind::ForLint => {
let unwind_drop = self let unwind_drop = self
.scopes .scopes
.unwind_drops .unwind_drops

View file

@ -12,10 +12,9 @@ fn method_1(_1: Guard) -> () {
let _8: OtherDrop; let _8: OtherDrop;
let _9: (); let _9: ();
let mut _10: bool; let mut _10: bool;
let mut _11: bool; let mut _11: isize;
let mut _12: isize; let mut _12: isize;
let mut _13: isize; let mut _13: isize;
let mut _14: isize;
scope 1 { scope 1 {
debug other_drop => _8; debug other_drop => _8;
} }
@ -24,7 +23,6 @@ fn method_1(_1: Guard) -> () {
} }
bb0: { bb0: {
_11 = const false;
_10 = const false; _10 = const false;
StorageLive(_2); StorageLive(_2);
StorageLive(_3); StorageLive(_3);
@ -32,15 +30,14 @@ fn method_1(_1: Guard) -> () {
StorageLive(_5); StorageLive(_5);
StorageLive(_6); StorageLive(_6);
_6 = &_1; _6 = &_1;
_5 = <Guard as Clone>::clone(move _6) -> [return: bb1, unwind: bb16]; _5 = <Guard as Clone>::clone(move _6) -> [return: bb1, unwind: bb13];
} }
bb1: { bb1: {
_11 = const true;
StorageDead(_6); StorageDead(_6);
_4 = &_5; _4 = &_5;
_3 = &(*_4); _3 = &(*_4);
_2 = method_2(move _3) -> [return: bb2, unwind: bb14]; _2 = method_2(move _3) -> [return: bb2, unwind: bb12];
} }
bb2: { bb2: {
@ -78,20 +75,19 @@ fn method_1(_1: Guard) -> () {
bb7: { bb7: {
backward incompatible drop(_2); backward incompatible drop(_2);
backward incompatible drop(_5); backward incompatible drop(_5);
goto -> bb24; goto -> bb21;
} }
bb8: { bb8: {
drop(_5) -> [return: bb9, unwind: bb16]; drop(_5) -> [return: bb9, unwind: bb13];
} }
bb9: { bb9: {
_11 = const false;
StorageDead(_5); StorageDead(_5);
StorageDead(_4); StorageDead(_4);
_10 = const false; _10 = const false;
StorageDead(_2); StorageDead(_2);
drop(_1) -> [return: bb10, unwind: bb17]; drop(_1) -> [return: bb10, unwind: bb14];
} }
bb10: { bb10: {
@ -99,7 +95,7 @@ fn method_1(_1: Guard) -> () {
} }
bb11 (cleanup): { bb11 (cleanup): {
goto -> bb28; goto -> bb25;
} }
bb12 (cleanup): { bb12 (cleanup): {
@ -107,77 +103,57 @@ fn method_1(_1: Guard) -> () {
} }
bb13 (cleanup): { bb13 (cleanup): {
goto -> bb15; drop(_1) -> [return: bb14, unwind terminate(cleanup)];
} }
bb14 (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; resume;
} }
bb18: { bb15: {
goto -> bb8; goto -> bb8;
} }
bb19 (cleanup): { bb16 (cleanup): {
goto -> bb12;
}
bb17 (cleanup): {
goto -> bb12;
}
bb18: {
goto -> bb15;
}
bb19: {
goto -> bb15; goto -> bb15;
} }
bb20 (cleanup): { bb20 (cleanup): {
goto -> bb15; goto -> bb12;
} }
bb21: { bb21: {
goto -> bb18; _11 = discriminant(_2);
switchInt(move _11) -> [0: bb18, otherwise: bb19];
} }
bb22: { bb22 (cleanup): {
goto -> bb18; _12 = discriminant(_2);
switchInt(move _12) -> [0: bb16, otherwise: bb20];
} }
bb23 (cleanup): { bb23 (cleanup): {
goto -> bb15; goto -> bb12;
} }
bb24: { bb24 (cleanup): {
_12 = discriminant(_2); goto -> bb12;
switchInt(move _12) -> [0: bb21, otherwise: bb22];
} }
bb25 (cleanup): { bb25 (cleanup): {
_13 = discriminant(_2); _13 = discriminant(_2);
switchInt(move _13) -> [0: bb19, otherwise: bb23]; switchInt(move _13) -> [0: bb23, otherwise: bb24];
}
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];
} }
} }

View file

@ -12,10 +12,9 @@ fn method_1(_1: Guard) -> () {
let _8: OtherDrop; let _8: OtherDrop;
let _9: (); let _9: ();
let mut _10: bool; let mut _10: bool;
let mut _11: bool; let mut _11: isize;
let mut _12: isize; let mut _12: isize;
let mut _13: isize; let mut _13: isize;
let mut _14: isize;
scope 1 { scope 1 {
debug other_drop => _8; debug other_drop => _8;
} }
@ -24,7 +23,6 @@ fn method_1(_1: Guard) -> () {
} }
bb0: { bb0: {
_11 = const false;
_10 = const false; _10 = const false;
StorageLive(_2); StorageLive(_2);
StorageLive(_3); StorageLive(_3);
@ -32,15 +30,14 @@ fn method_1(_1: Guard) -> () {
StorageLive(_5); StorageLive(_5);
StorageLive(_6); StorageLive(_6);
_6 = &_1; _6 = &_1;
_5 = <Guard as Clone>::clone(move _6) -> [return: bb1, unwind: bb16]; _5 = <Guard as Clone>::clone(move _6) -> [return: bb1, unwind: bb13];
} }
bb1: { bb1: {
_11 = const true;
StorageDead(_6); StorageDead(_6);
_4 = &_5; _4 = &_5;
_3 = &(*_4); _3 = &(*_4);
_2 = method_2(move _3) -> [return: bb2, unwind: bb14]; _2 = method_2(move _3) -> [return: bb2, unwind: bb12];
} }
bb2: { bb2: {
@ -78,20 +75,19 @@ fn method_1(_1: Guard) -> () {
bb7: { bb7: {
backward incompatible drop(_2); backward incompatible drop(_2);
backward incompatible drop(_5); backward incompatible drop(_5);
goto -> bb24; goto -> bb21;
} }
bb8: { bb8: {
drop(_5) -> [return: bb9, unwind: bb16]; drop(_5) -> [return: bb9, unwind: bb13];
} }
bb9: { bb9: {
_11 = const false;
StorageDead(_5); StorageDead(_5);
StorageDead(_4); StorageDead(_4);
_10 = const false; _10 = const false;
StorageDead(_2); StorageDead(_2);
drop(_1) -> [return: bb10, unwind: bb17]; drop(_1) -> [return: bb10, unwind: bb14];
} }
bb10: { bb10: {
@ -99,7 +95,7 @@ fn method_1(_1: Guard) -> () {
} }
bb11 (cleanup): { bb11 (cleanup): {
goto -> bb28; goto -> bb25;
} }
bb12 (cleanup): { bb12 (cleanup): {
@ -107,77 +103,57 @@ fn method_1(_1: Guard) -> () {
} }
bb13 (cleanup): { bb13 (cleanup): {
goto -> bb15; drop(_1) -> [return: bb14, unwind terminate(cleanup)];
} }
bb14 (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; resume;
} }
bb18: { bb15: {
goto -> bb8; goto -> bb8;
} }
bb19 (cleanup): { bb16 (cleanup): {
goto -> bb12;
}
bb17 (cleanup): {
goto -> bb12;
}
bb18: {
goto -> bb15;
}
bb19: {
goto -> bb15; goto -> bb15;
} }
bb20 (cleanup): { bb20 (cleanup): {
goto -> bb15; goto -> bb12;
} }
bb21: { bb21: {
goto -> bb18; _11 = discriminant(_2);
switchInt(move _11) -> [0: bb18, otherwise: bb19];
} }
bb22: { bb22 (cleanup): {
goto -> bb18; _12 = discriminant(_2);
switchInt(move _12) -> [0: bb16, otherwise: bb20];
} }
bb23 (cleanup): { bb23 (cleanup): {
goto -> bb15; goto -> bb12;
} }
bb24: { bb24 (cleanup): {
_12 = discriminant(_2); goto -> bb12;
switchInt(move _12) -> [0: bb21, otherwise: bb22];
} }
bb25 (cleanup): { bb25 (cleanup): {
_13 = discriminant(_2); _13 = discriminant(_2);
switchInt(move _13) -> [0: bb19, otherwise: bb23]; switchInt(move _13) -> [0: bb23, otherwise: bb24];
}
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];
} }
} }

View file

@ -26,8 +26,8 @@ fn method_1(g: Guard) {
match method_2(&g.clone()) { match method_2(&g.clone()) {
Ok(other_drop) => { Ok(other_drop) => {
// repro needs something else being dropped too. // repro needs something else being dropped too.
}, }
Err(err) => {}, Err(err) => {}
} }
} }