summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src/remove_unneeded_drops.rs')
-rw-r--r--compiler/rustc_mir_transform/src/remove_unneeded_drops.rs45
1 files changed, 45 insertions, 0 deletions
diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
new file mode 100644
index 000000000..84ccf6e1f
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
@@ -0,0 +1,45 @@
+//! This pass replaces a drop of a type that does not need dropping, with a goto.
+//!
+//! When the MIR is built, we check `needs_drop` before emitting a `Drop` for a place. This pass is
+//! useful because (unlike MIR building) it runs after type checking, so it can make use of
+//! `Reveal::All` to provide more precise type information.
+
+use crate::MirPass;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+use super::simplify::simplify_cfg;
+
+pub struct RemoveUnneededDrops;
+
+impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ trace!("Running RemoveUnneededDrops on {:?}", body.source);
+
+ let did = body.source.def_id();
+ let param_env = tcx.param_env_reveal_all_normalized(did);
+ let mut should_simplify = false;
+
+ for block in body.basic_blocks.as_mut() {
+ let terminator = block.terminator_mut();
+ if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
+ let ty = place.ty(&body.local_decls, tcx);
+ if ty.ty.needs_drop(tcx, param_env) {
+ continue;
+ }
+ if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", did)) {
+ continue;
+ }
+ debug!("SUCCESS: replacing `drop` with goto({:?})", target);
+ terminator.kind = TerminatorKind::Goto { target };
+ should_simplify = true;
+ }
+ }
+
+ // if we applied optimizations, we potentially have some cfg to cleanup to
+ // make it easier for further passes
+ if should_simplify {
+ simplify_cfg(tcx, body);
+ }
+ }
+}