@@ -409,8 +409,15 @@ where
409
409
self . drop_ladder ( fields, succ, unwind) . 0
410
410
}
411
411
412
+ /// Drops the T contained in a `Box<T>` if it has not been moved out of
412
413
#[ 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 {
414
421
// drop glue is sent straight to codegen
415
422
// box cannot be directly dereferenced
416
423
let unique_ty = adt. non_enum_variant ( ) . fields [ FieldIdx :: new ( 0 ) ] . ty ( self . tcx ( ) , substs) ;
@@ -425,11 +432,7 @@ where
425
432
426
433
let interior_path = self . elaborator . deref_subpath ( self . path ) ;
427
434
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)
433
436
}
434
437
435
438
#[ instrument( level = "debug" , ret) ]
@@ -453,7 +456,15 @@ where
453
456
self . open_drop_for_adt_contents ( adt, substs)
454
457
} ;
455
458
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 ( ) ) {
457
468
self . destructor_call_block ( contents_drop)
458
469
} else {
459
470
contents_drop. 0
@@ -650,7 +661,13 @@ where
650
661
} ) ,
651
662
is_cleanup : unwind. is_cleanup ( ) ,
652
663
} ;
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)
654
671
}
655
672
656
673
/// Create a loop that drops an array:
@@ -851,13 +868,7 @@ where
851
868
self . open_drop_for_tuple ( & tys)
852
869
}
853
870
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) ,
861
872
ty:: Dynamic ( ..) => self . complete_drop ( self . succ , self . unwind ) ,
862
873
ty:: Array ( ety, size) => {
863
874
let size = size. try_eval_target_usize ( self . tcx ( ) , self . elaborator . param_env ( ) ) ;
@@ -905,65 +916,6 @@ where
905
916
blk
906
917
}
907
918
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
-
967
919
fn drop_block ( & mut self , target : BasicBlock , unwind : Unwind ) -> BasicBlock {
968
920
let block = TerminatorKind :: Drop {
969
921
place : self . place ,
0 commit comments