Rollup merge of #108856 - Zeegomo:remove-drop-and-rep, r=tmiasko
Remove DropAndReplace terminator #107844 made DropAndReplace unused, let's remove it completely from the codebase.
This commit is contained in:
commit
4e84fbf8a0
48 changed files with 33 additions and 344 deletions
|
@ -74,7 +74,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
|
|||
};
|
||||
layout::fn_can_unwind(tcx, fn_def_id, sig.abi())
|
||||
}
|
||||
TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => {
|
||||
TerminatorKind::Drop { .. } => {
|
||||
tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Unwind
|
||||
&& layout::fn_can_unwind(tcx, None, Abi::Rust)
|
||||
}
|
||||
|
|
|
@ -64,9 +64,6 @@ fn add_moves_for_packed_drops_patch<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>)
|
|||
{
|
||||
add_move_for_packed_drop(tcx, body, &mut patch, terminator, loc, data.is_cleanup);
|
||||
}
|
||||
TerminatorKind::DropAndReplace { .. } => {
|
||||
span_bug!(terminator.source_info.span, "replace in AddMovesForPackedDrops");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
|
|||
}
|
||||
|
||||
// `Drop` is also a call, but it doesn't return anything so we are good.
|
||||
TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => None,
|
||||
TerminatorKind::Drop { .. } => None,
|
||||
// Not a block ending in a Call -> ignore.
|
||||
_ => None,
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
|
|||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::Yield { .. }
|
||||
| TerminatorKind::Assert { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::Resume
|
||||
| TerminatorKind::Abort
|
||||
|
|
|
@ -1007,7 +1007,6 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
|
|||
| TerminatorKind::Return
|
||||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Yield { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::FalseEdge { .. }
|
||||
|
|
|
@ -686,7 +686,6 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
|
|||
| TerminatorKind::Return
|
||||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Yield { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::FalseEdge { .. }
|
||||
|
|
|
@ -822,7 +822,6 @@ pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str {
|
|||
TerminatorKind::Return => "Return",
|
||||
TerminatorKind::Unreachable => "Unreachable",
|
||||
TerminatorKind::Drop { .. } => "Drop",
|
||||
TerminatorKind::DropAndReplace { .. } => "DropAndReplace",
|
||||
TerminatorKind::Call { .. } => "Call",
|
||||
TerminatorKind::Assert { .. } => "Assert",
|
||||
TerminatorKind::Yield { .. } => "Yield",
|
||||
|
|
|
@ -156,7 +156,6 @@ impl CoverageGraph {
|
|||
| TerminatorKind::Resume
|
||||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Call { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::Assert { .. }
|
||||
|
|
|
@ -850,7 +850,6 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp
|
|||
TerminatorKind::Unreachable // Unreachable blocks are not connected to the MIR CFG
|
||||
| TerminatorKind::Assert { .. }
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::SwitchInt { .. }
|
||||
// For `FalseEdge`, only the `real` branch is taken, so it is similar to a `Goto`.
|
||||
| TerminatorKind::FalseEdge { .. }
|
||||
|
|
|
@ -86,7 +86,6 @@ impl<'tcx> MockBlocks<'tcx> {
|
|||
TerminatorKind::Assert { ref mut target, .. }
|
||||
| TerminatorKind::Call { target: Some(ref mut target), .. }
|
||||
| TerminatorKind::Drop { ref mut target, .. }
|
||||
| TerminatorKind::DropAndReplace { ref mut target, .. }
|
||||
| TerminatorKind::FalseEdge { real_target: ref mut target, .. }
|
||||
| TerminatorKind::FalseUnwind { real_target: ref mut target, .. }
|
||||
| TerminatorKind::Goto { ref mut target }
|
||||
|
@ -184,7 +183,6 @@ fn debug_basic_blocks(mir_body: &Body<'_>) -> String {
|
|||
TerminatorKind::Assert { target, .. }
|
||||
| TerminatorKind::Call { target: Some(target), .. }
|
||||
| TerminatorKind::Drop { target, .. }
|
||||
| TerminatorKind::DropAndReplace { target, .. }
|
||||
| TerminatorKind::FalseEdge { real_target: target, .. }
|
||||
| TerminatorKind::FalseUnwind { real_target: target, .. }
|
||||
| TerminatorKind::Goto { target }
|
||||
|
|
|
@ -650,8 +650,7 @@ impl WriteInfo {
|
|||
TerminatorKind::Drop { .. } => {
|
||||
// `Drop`s create a `&mut` and so are not considered
|
||||
}
|
||||
TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Yield { .. }
|
||||
TerminatorKind::Yield { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::FalseEdge { .. }
|
||||
| TerminatorKind::FalseUnwind { .. } => {
|
||||
|
|
|
@ -18,15 +18,14 @@ use rustc_span::{DesugaringKind, Span};
|
|||
use rustc_target::abi::VariantIdx;
|
||||
use std::fmt;
|
||||
|
||||
/// During MIR building, Drop and DropAndReplace terminators are inserted in every place where a drop may occur.
|
||||
/// During MIR building, Drop terminators are inserted in every place where a drop may occur.
|
||||
/// However, in this phase, the presence of these terminators does not guarantee that a destructor will run,
|
||||
/// as the target of the drop may be uninitialized.
|
||||
/// In general, the compiler cannot determine at compile time whether a destructor will run or not.
|
||||
///
|
||||
/// At a high level, this pass refines Drop and DropAndReplace to only run the destructor if the
|
||||
/// At a high level, this pass refines Drop to only run the destructor if the
|
||||
/// target is initialized. The way this is achievied is by inserting drop flags for every variable
|
||||
/// that may be dropped, and then using those flags to determine whether a destructor should run.
|
||||
/// This pass also removes DropAndReplace, replacing it with a Drop paired with an assign statement.
|
||||
/// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or
|
||||
/// "drop shim" for the type of the dropped place.
|
||||
///
|
||||
|
@ -121,8 +120,7 @@ fn remove_dead_unwinds<'tcx>(
|
|||
.into_results_cursor(body);
|
||||
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
|
||||
let place = match bb_data.terminator().kind {
|
||||
TerminatorKind::Drop { ref place, unwind: Some(_), .. }
|
||||
| TerminatorKind::DropAndReplace { ref place, unwind: Some(_), .. } => {
|
||||
TerminatorKind::Drop { ref place, unwind: Some(_), .. } => {
|
||||
und.derefer(place.as_ref(), body).unwrap_or(*place)
|
||||
}
|
||||
_ => continue,
|
||||
|
@ -343,8 +341,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||
}
|
||||
let terminator = data.terminator();
|
||||
let place = match terminator.kind {
|
||||
TerminatorKind::Drop { ref place, .. }
|
||||
| TerminatorKind::DropAndReplace { ref place, .. } => {
|
||||
TerminatorKind::Drop { ref place, .. } => {
|
||||
self.un_derefer.derefer(place.as_ref(), self.body).unwrap_or(*place)
|
||||
}
|
||||
_ => continue,
|
||||
|
@ -441,103 +438,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
TerminatorKind::DropAndReplace { mut place, ref value, target, unwind } => {
|
||||
assert!(!data.is_cleanup);
|
||||
|
||||
if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) {
|
||||
place = new_place;
|
||||
}
|
||||
self.elaborate_replace(loc, place, value, target, unwind);
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Elaborate a MIR `replace` terminator. This instruction
|
||||
/// is not directly handled by codegen, and therefore
|
||||
/// must be desugared.
|
||||
///
|
||||
/// The desugaring drops the location if needed, and then writes
|
||||
/// the value (including setting the drop flag) over it in *both* arms.
|
||||
///
|
||||
/// The `replace` terminator can also be called on places that
|
||||
/// are not tracked by elaboration (for example,
|
||||
/// `replace x[i] <- tmp0`). The borrow checker requires that
|
||||
/// these locations are initialized before the assignment,
|
||||
/// so we just generate an unconditional drop.
|
||||
fn elaborate_replace(
|
||||
&mut self,
|
||||
loc: Location,
|
||||
place: Place<'tcx>,
|
||||
value: &Operand<'tcx>,
|
||||
target: BasicBlock,
|
||||
unwind: Option<BasicBlock>,
|
||||
) {
|
||||
let bb = loc.block;
|
||||
let data = &self.body[bb];
|
||||
let terminator = data.terminator();
|
||||
assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported");
|
||||
|
||||
let assign = Statement {
|
||||
kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value.clone())))),
|
||||
source_info: terminator.source_info,
|
||||
};
|
||||
|
||||
let unwind = unwind.unwrap_or_else(|| self.patch.resume_block());
|
||||
let unwind = self.patch.new_block(BasicBlockData {
|
||||
statements: vec![assign.clone()],
|
||||
terminator: Some(Terminator {
|
||||
kind: TerminatorKind::Goto { target: unwind },
|
||||
..*terminator
|
||||
}),
|
||||
is_cleanup: true,
|
||||
});
|
||||
|
||||
let target = self.patch.new_block(BasicBlockData {
|
||||
statements: vec![assign],
|
||||
terminator: Some(Terminator { kind: TerminatorKind::Goto { target }, ..*terminator }),
|
||||
is_cleanup: false,
|
||||
});
|
||||
|
||||
match self.move_data().rev_lookup.find(place.as_ref()) {
|
||||
LookupResult::Exact(path) => {
|
||||
debug!("elaborate_drop_and_replace({:?}) - tracked {:?}", terminator, path);
|
||||
self.init_data.seek_before(loc);
|
||||
elaborate_drop(
|
||||
&mut Elaborator { ctxt: self },
|
||||
terminator.source_info,
|
||||
place,
|
||||
path,
|
||||
target,
|
||||
Unwind::To(unwind),
|
||||
bb,
|
||||
);
|
||||
on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| {
|
||||
self.set_drop_flag(
|
||||
Location { block: target, statement_index: 0 },
|
||||
child,
|
||||
DropFlagState::Present,
|
||||
);
|
||||
self.set_drop_flag(
|
||||
Location { block: unwind, statement_index: 0 },
|
||||
child,
|
||||
DropFlagState::Present,
|
||||
);
|
||||
});
|
||||
}
|
||||
LookupResult::Parent(parent) => {
|
||||
// drop and replace behind a pointer/array/whatever. The location
|
||||
// must be initialized.
|
||||
debug!("elaborate_drop_and_replace({:?}) - untracked {:?}", terminator, parent);
|
||||
self.patch.patch_terminator(
|
||||
bb,
|
||||
TerminatorKind::Drop { place, target, unwind: Some(unwind) },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
|
||||
Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||
span,
|
||||
|
@ -609,22 +514,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||
debug!("drop_flags_for_locs({:?})", data);
|
||||
for i in 0..(data.statements.len() + 1) {
|
||||
debug!("drop_flag_for_locs: stmt {}", i);
|
||||
let mut allow_initializations = true;
|
||||
if i == data.statements.len() {
|
||||
match data.terminator().kind {
|
||||
TerminatorKind::Drop { .. } => {
|
||||
// drop elaboration should handle that by itself
|
||||
continue;
|
||||
}
|
||||
TerminatorKind::DropAndReplace { .. } => {
|
||||
// this contains the move of the source and
|
||||
// the initialization of the destination. We
|
||||
// only want the former - the latter is handled
|
||||
// by the elaboration code and must be done
|
||||
// *after* the destination is dropped.
|
||||
assert!(self.patch.is_patched(bb));
|
||||
allow_initializations = false;
|
||||
}
|
||||
TerminatorKind::Resume => {
|
||||
// It is possible for `Resume` to be patched
|
||||
// (in particular it can be patched to be replaced with
|
||||
|
@ -641,11 +536,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
|||
self.body,
|
||||
self.env,
|
||||
loc,
|
||||
|path, ds| {
|
||||
if ds == DropFlagState::Absent || allow_initializations {
|
||||
self.set_drop_flag(loc, path, ds)
|
||||
}
|
||||
},
|
||||
|path, ds| self.set_drop_flag(loc, path, ds),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1199,7 +1199,6 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
|
|||
|
||||
// These may unwind.
|
||||
TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Call { .. }
|
||||
| TerminatorKind::InlineAsm { .. }
|
||||
| TerminatorKind::Assert { .. } => return true,
|
||||
|
@ -1691,7 +1690,6 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
|
|||
| TerminatorKind::Return
|
||||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Assert { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::FalseEdge { .. }
|
||||
|
|
|
@ -453,9 +453,7 @@ impl<'tcx> Inliner<'tcx> {
|
|||
checker.visit_basic_block_data(bb, blk);
|
||||
|
||||
let term = blk.terminator();
|
||||
if let TerminatorKind::Drop { ref place, target, unwind }
|
||||
| TerminatorKind::DropAndReplace { ref place, target, unwind, .. } = term.kind
|
||||
{
|
||||
if let TerminatorKind::Drop { ref place, target, unwind } = term.kind {
|
||||
work_list.push(target);
|
||||
|
||||
// If the place doesn't actually need dropping, treat it like a regular goto.
|
||||
|
@ -815,8 +813,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
|
|||
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
||||
let tcx = self.tcx;
|
||||
match terminator.kind {
|
||||
TerminatorKind::Drop { ref place, unwind, .. }
|
||||
| TerminatorKind::DropAndReplace { ref place, unwind, .. } => {
|
||||
TerminatorKind::Drop { ref place, unwind, .. } => {
|
||||
// If the place doesn't actually need dropping, treat it like a regular goto.
|
||||
let ty = self.instance.subst_mir(tcx, &place.ty(self.callee_body, tcx).ty);
|
||||
if ty.needs_drop(tcx, self.param_env) {
|
||||
|
@ -1120,8 +1117,7 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
|
|||
*tgt = self.map_block(*tgt);
|
||||
}
|
||||
}
|
||||
TerminatorKind::Drop { ref mut target, ref mut unwind, .. }
|
||||
| TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => {
|
||||
TerminatorKind::Drop { ref mut target, ref mut unwind, .. } => {
|
||||
*target = self.map_block(*target);
|
||||
*unwind = self.map_unwind(*unwind);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,6 @@ impl RemoveNoopLandingPads {
|
|||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::Call { .. }
|
||||
| TerminatorKind::Assert { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::InlineAsm { .. } => false,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_index::bit_set::ChunkedBitSet;
|
||||
use rustc_middle::mir::{Body, Field, Rvalue, Statement, StatementKind, TerminatorKind};
|
||||
use rustc_middle::mir::{Body, Field, TerminatorKind};
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
|
||||
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
||||
|
@ -8,7 +8,7 @@ use rustc_mir_dataflow::{self, move_path_children_matching, Analysis, MoveDataPa
|
|||
|
||||
use crate::MirPass;
|
||||
|
||||
/// Removes `Drop` and `DropAndReplace` terminators whose target is known to be uninitialized at
|
||||
/// Removes `Drop` terminators whose target is known to be uninitialized at
|
||||
/// that point.
|
||||
///
|
||||
/// This is redundant with drop elaboration, but we need to do it prior to const-checking, and
|
||||
|
@ -37,8 +37,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
|
|||
let mut to_remove = vec![];
|
||||
for (bb, block) in body.basic_blocks.iter_enumerated() {
|
||||
let terminator = block.terminator();
|
||||
let (TerminatorKind::Drop { place, .. } | TerminatorKind::DropAndReplace { place, .. })
|
||||
= &terminator.kind
|
||||
let TerminatorKind::Drop { place, .. } = &terminator.kind
|
||||
else { continue };
|
||||
|
||||
maybe_inits.seek_before_primary_effect(body.terminator_loc(bb));
|
||||
|
@ -64,24 +63,12 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
|
|||
for bb in to_remove {
|
||||
let block = &mut body.basic_blocks_mut()[bb];
|
||||
|
||||
let (TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. })
|
||||
let TerminatorKind::Drop { target, .. }
|
||||
= &block.terminator().kind
|
||||
else { unreachable!() };
|
||||
|
||||
// Replace block terminator with `Goto`.
|
||||
let target = *target;
|
||||
let old_terminator_kind = std::mem::replace(
|
||||
&mut block.terminator_mut().kind,
|
||||
TerminatorKind::Goto { target },
|
||||
);
|
||||
|
||||
// If this is a `DropAndReplace`, we need to emulate the assignment to the return place.
|
||||
if let TerminatorKind::DropAndReplace { place, value, .. } = old_terminator_kind {
|
||||
block.statements.push(Statement {
|
||||
source_info: block.terminator().source_info,
|
||||
kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value)))),
|
||||
});
|
||||
}
|
||||
block.terminator_mut().kind = TerminatorKind::Goto { target: *target };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,6 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
|
|||
// The following terminators are not allowed
|
||||
TerminatorKind::Resume
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Call { .. }
|
||||
| TerminatorKind::Assert { .. }
|
||||
| TerminatorKind::FalseUnwind { .. }
|
||||
|
@ -170,7 +169,6 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
|
|||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::Assert { .. }
|
||||
| TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::FalseUnwind { .. }
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::Call { .. }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue