@@ -409,8 +409,15 @@ where
409409 self . drop_ladder ( fields, succ, unwind) . 0
410410 }
411411
412+ /// Drops the T contained in a `Box<T>` if it has not been moved out of
412413 #[ instrument( level = "debug" , ret) ]
413- fn open_drop_for_box ( & mut self , adt : ty:: AdtDef < ' tcx > , substs : SubstsRef < ' tcx > ) -> BasicBlock {
414+ fn open_drop_for_box_contents (
415+ & mut self ,
416+ adt : ty:: AdtDef < ' tcx > ,
417+ substs : SubstsRef < ' tcx > ,
418+ succ : BasicBlock ,
419+ unwind : Unwind ,
420+ ) -> BasicBlock {
414421 // drop glue is sent straight to codegen
415422 // box cannot be directly dereferenced
416423 let unique_ty = adt. non_enum_variant ( ) . fields [ FieldIdx :: new ( 0 ) ] . ty ( self . tcx ( ) , substs) ;
@@ -425,11 +432,7 @@ where
425432
426433 let interior_path = self . elaborator . deref_subpath ( self . path ) ;
427434
428- let succ = self . box_free_block ( adt, substs, self . succ , self . unwind ) ;
429- let unwind_succ =
430- self . unwind . map ( |unwind| self . box_free_block ( adt, substs, unwind, Unwind :: InCleanup ) ) ;
431-
432- self . drop_subpath ( interior, interior_path, succ, unwind_succ)
435+ self . drop_subpath ( interior, interior_path, succ, unwind)
433436 }
434437
435438 #[ instrument( level = "debug" , ret) ]
@@ -453,7 +456,15 @@ where
453456 self . open_drop_for_adt_contents ( adt, substs)
454457 } ;
455458
456- if adt. has_dtor ( self . tcx ( ) ) {
459+ if adt. is_box ( ) {
460+ // we need to drop the inside of the box before running the destructor
461+ let succ = self . destructor_call_block ( contents_drop) ;
462+ let unwind = contents_drop
463+ . 1
464+ . map ( |unwind| self . destructor_call_block ( ( unwind, Unwind :: InCleanup ) ) ) ;
465+
466+ self . open_drop_for_box_contents ( adt, substs, succ, unwind)
467+ } else if adt. has_dtor ( self . tcx ( ) ) {
457468 self . destructor_call_block ( contents_drop)
458469 } else {
459470 contents_drop. 0
@@ -650,7 +661,13 @@ where
650661 } ) ,
651662 is_cleanup : unwind. is_cleanup ( ) ,
652663 } ;
653- self . elaborator . patch ( ) . new_block ( result)
664+
665+ let destructor_block = self . elaborator . patch ( ) . new_block ( result) ;
666+
667+ let block_start = Location { block : destructor_block, statement_index : 0 } ;
668+ self . elaborator . clear_drop_flag ( block_start, self . path , DropFlagMode :: Shallow ) ;
669+
670+ self . drop_flag_test_block ( destructor_block, succ, unwind)
654671 }
655672
656673 /// Create a loop that drops an array:
@@ -851,13 +868,7 @@ where
851868 self . open_drop_for_tuple ( & tys)
852869 }
853870 ty:: Tuple ( fields) => self . open_drop_for_tuple ( fields) ,
854- ty:: Adt ( def, substs) => {
855- if def. is_box ( ) {
856- self . open_drop_for_box ( * def, substs)
857- } else {
858- self . open_drop_for_adt ( * def, substs)
859- }
860- }
871+ ty:: Adt ( def, substs) => self . open_drop_for_adt ( * def, substs) ,
861872 ty:: Dynamic ( ..) => self . complete_drop ( self . succ , self . unwind ) ,
862873 ty:: Array ( ety, size) => {
863874 let size = size. try_eval_target_usize ( self . tcx ( ) , self . elaborator . param_env ( ) ) ;
@@ -905,65 +916,6 @@ where
905916 blk
906917 }
907918
908- /// Creates a block that frees the backing memory of a `Box` if its drop is required (either
909- /// statically or by checking its drop flag).
910- ///
911- /// The contained value will not be dropped.
912- fn box_free_block (
913- & mut self ,
914- adt : ty:: AdtDef < ' tcx > ,
915- substs : SubstsRef < ' tcx > ,
916- target : BasicBlock ,
917- unwind : Unwind ,
918- ) -> BasicBlock {
919- let block = self . unelaborated_free_block ( adt, substs, target, unwind) ;
920- self . drop_flag_test_block ( block, target, unwind)
921- }
922-
923- /// Creates a block that frees the backing memory of a `Box` (without dropping the contained
924- /// value).
925- fn unelaborated_free_block (
926- & mut self ,
927- adt : ty:: AdtDef < ' tcx > ,
928- substs : SubstsRef < ' tcx > ,
929- target : BasicBlock ,
930- unwind : Unwind ,
931- ) -> BasicBlock {
932- let tcx = self . tcx ( ) ;
933- let unit_temp = Place :: from ( self . new_temp ( tcx. mk_unit ( ) ) ) ;
934- let free_func = tcx. require_lang_item ( LangItem :: BoxFree , Some ( self . source_info . span ) ) ;
935- let args = adt
936- . variant ( FIRST_VARIANT )
937- . fields
938- . iter ( )
939- . enumerate ( )
940- . map ( |( i, f) | {
941- let field = FieldIdx :: new ( i) ;
942- let field_ty = f. ty ( tcx, substs) ;
943- Operand :: Move ( tcx. mk_place_field ( self . place , field, field_ty) )
944- } )
945- . collect ( ) ;
946-
947- let call = TerminatorKind :: Call {
948- func : Operand :: function_handle ( tcx, free_func, substs, self . source_info . span ) ,
949- args,
950- destination : unit_temp,
951- target : Some ( target) ,
952- unwind : if unwind. is_cleanup ( ) {
953- UnwindAction :: Terminate
954- } else {
955- UnwindAction :: Continue
956- } ,
957- from_hir_call : false ,
958- fn_span : self . source_info . span ,
959- } ; // FIXME(#43234)
960- let free_block = self . new_block ( unwind, call) ;
961-
962- let block_start = Location { block : free_block, statement_index : 0 } ;
963- self . elaborator . clear_drop_flag ( block_start, self . path , DropFlagMode :: Shallow ) ;
964- free_block
965- }
966-
967919 fn drop_block ( & mut self , target : BasicBlock , unwind : Unwind ) -> BasicBlock {
968920 let block = TerminatorKind :: Drop {
969921 place : self . place ,
0 commit comments