]>
Commit | Line | Data |
---|---|---|
a2a8927a XL |
1 | //! This pass replaces a drop of a type that does not need dropping, with a goto. |
2 | //! | |
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 | |
5e7ed085 | 5 | //! `Reveal::All` to provide more precise type information. |
1b1a35ee | 6 | |
1b1a35ee | 7 | use rustc_middle::mir::*; |
5869c6ff | 8 | use rustc_middle::ty::TyCtxt; |
1b1a35ee XL |
9 | |
10 | use super::simplify::simplify_cfg; | |
11 | ||
12 | pub struct RemoveUnneededDrops; | |
13 | ||
14 | impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { | |
29967ef6 XL |
15 | fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { |
16 | trace!("Running RemoveUnneededDrops on {:?}", body.source); | |
fc512014 | 17 | |
5869c6ff | 18 | let did = body.source.def_id(); |
3c0e092e | 19 | let param_env = tcx.param_env_reveal_all_normalized(did); |
5869c6ff XL |
20 | let mut should_simplify = false; |
21 | ||
064997fb | 22 | for block in body.basic_blocks.as_mut() { |
5869c6ff XL |
23 | let terminator = block.terminator_mut(); |
24 | if let TerminatorKind::Drop { place, target, .. } = terminator.kind { | |
064997fb | 25 | let ty = place.ty(&body.local_decls, tcx); |
5869c6ff XL |
26 | if ty.ty.needs_drop(tcx, param_env) { |
27 | continue; | |
28 | } | |
add651ee | 29 | if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {did:?} ")) { |
5869c6ff XL |
30 | continue; |
31 | } | |
32 | debug!("SUCCESS: replacing `drop` with goto({:?})", target); | |
33 | terminator.kind = TerminatorKind::Goto { target }; | |
34 | should_simplify = true; | |
35 | } | |
1b1a35ee XL |
36 | } |
37 | ||
38 | // if we applied optimizations, we potentially have some cfg to cleanup to | |
39 | // make it easier for further passes | |
40 | if should_simplify { | |
c0240ec0 | 41 | simplify_cfg(body); |
1b1a35ee XL |
42 | } |
43 | } | |
44 | } |