1 //! This pass replaces a drop of a type that does not need dropping, with a goto.
3 //! When the MIR is built, we check `needs_drop` before emitting a `Drop` for a place. This pass is
4 //! useful because (unlike MIR building) it runs after type checking, so it can make use of
5 //! `Reveal::All` to provide more precies type information.
8 use rustc_middle::mir::*;
9 use rustc_middle::ty::TyCtxt;
11 use super::simplify::simplify_cfg;
13 pub struct RemoveUnneededDrops;
15 impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
16 fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
17 trace!("Running RemoveUnneededDrops on {:?}", body.source);
19 let did = body.source.def_id();
20 let param_env = tcx.param_env_reveal_all_normalized(did);
21 let mut should_simplify = false;
23 let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
24 for block in basic_blocks {
25 let terminator = block.terminator_mut();
26 if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
27 let ty = place.ty(local_decls, tcx);
28 if ty.ty.needs_drop(tcx, param_env) {
31 if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", did)) {
34 debug!("SUCCESS: replacing `drop` with goto({:?})", target);
35 terminator.kind = TerminatorKind::Goto { target };
36 should_simplify = true;
40 // if we applied optimizations, we potentially have some cfg to cleanup to
41 // make it easier for further passes
43 simplify_cfg(tcx, body);