44//! useful because (unlike MIR building) it runs after type checking, so it can make use of
55//! `TypingMode::PostAnalysis` to provide more precise type information, especially about opaque
66//! types.
7+ //!
8+ //! When we're optimizing, we also remove calls to `drop_in_place<T>` when `T` isn't `needs_drop`,
9+ //! as those are essentially equivalent to `Drop` terminators. While the compiler doesn't insert
10+ //! them automatically, preferring the built-in instead, they're common in generic code (such as
11+ //! `Vec::truncate`) so removing them from things like inlined `Vec<u8>` is helpful.
712
13+ use rustc_hir:: LangItem ;
814use rustc_middle:: mir:: * ;
915use rustc_middle:: ty:: TyCtxt ;
1016use tracing:: { debug, trace} ;
@@ -21,15 +27,26 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
2127 let mut should_simplify = false ;
2228 for block in body. basic_blocks . as_mut ( ) {
2329 let terminator = block. terminator_mut ( ) ;
24- if let TerminatorKind :: Drop { place, target, .. } = terminator. kind {
25- let ty = place. ty ( & body. local_decls , tcx) ;
26- if ty. ty . needs_drop ( tcx, typing_env) {
27- continue ;
30+ let ( ty, target) = match terminator. kind {
31+ TerminatorKind :: Drop { place, target, .. } => {
32+ ( place. ty ( & body. local_decls , tcx) . ty , target)
33+ }
34+ TerminatorKind :: Call { ref func, target : Some ( target) , .. }
35+ if tcx. sess . mir_opt_level ( ) > 0
36+ && let Some ( ( def_id, generics) ) = func. const_fn_def ( )
37+ && tcx. is_lang_item ( def_id, LangItem :: DropInPlace ) =>
38+ {
39+ ( generics. type_at ( 0 ) , target)
2840 }
29- debug ! ( "SUCCESS: replacing `drop` with goto({:?})" , target) ;
30- terminator. kind = TerminatorKind :: Goto { target } ;
31- should_simplify = true ;
41+ _ => continue ,
42+ } ;
43+
44+ if ty. needs_drop ( tcx, typing_env) {
45+ continue ;
3246 }
47+ debug ! ( "SUCCESS: replacing `drop` with goto({:?})" , target) ;
48+ terminator. kind = TerminatorKind :: Goto { target } ;
49+ should_simplify = true ;
3350 }
3451
3552 // if we applied optimizations, we potentially have some cfg to cleanup to
0 commit comments