@@ -337,18 +337,19 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
337
337
self . drop_ladder ( fields, succ, unwind) . 0
338
338
}
339
339
340
- fn open_drop_for_box < ' a > ( & mut self , ty : Ty < ' tcx > ) -> BasicBlock
340
+ fn open_drop_for_box < ' a > ( & mut self , adt : & ' tcx ty:: AdtDef , substs : & ' tcx Substs < ' tcx > )
341
+ -> BasicBlock
341
342
{
342
- debug ! ( "open_drop_for_box({:?}, {:?})" , self , ty ) ;
343
+ debug ! ( "open_drop_for_box({:?}, {:?}, {:?} )" , self , adt , substs ) ;
343
344
344
345
let interior = self . place . clone ( ) . deref ( ) ;
345
346
let interior_path = self . elaborator . deref_subpath ( self . path ) ;
346
347
347
348
let succ = self . succ ; // FIXME(#43234)
348
349
let unwind = self . unwind ;
349
- let succ = self . box_free_block ( ty , succ, unwind) ;
350
+ let succ = self . box_free_block ( adt , substs , succ, unwind) ;
350
351
let unwind_succ = self . unwind . map ( |unwind| {
351
- self . box_free_block ( ty , unwind, Unwind :: InCleanup )
352
+ self . box_free_block ( adt , substs , unwind, Unwind :: InCleanup )
352
353
} ) ;
353
354
354
355
self . drop_subpath ( & interior, interior_path, succ, unwind_succ)
@@ -791,11 +792,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
791
792
ty:: TyTuple ( tys) => {
792
793
self . open_drop_for_tuple ( tys)
793
794
}
794
- ty:: TyAdt ( def, _) if def. is_box ( ) => {
795
- self . open_drop_for_box ( ty. boxed_ty ( ) )
796
- }
797
795
ty:: TyAdt ( def, substs) => {
798
- self . open_drop_for_adt ( def, substs)
796
+ if def. is_box ( ) {
797
+ self . open_drop_for_box ( def, substs)
798
+ } else {
799
+ self . open_drop_for_adt ( def, substs)
800
+ }
799
801
}
800
802
ty:: TyDynamic ( ..) => {
801
803
let unwind = self . unwind ; // FIXME(#43234)
@@ -858,34 +860,40 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
858
860
859
861
fn box_free_block < ' a > (
860
862
& mut self ,
861
- ty : Ty < ' tcx > ,
863
+ adt : & ' tcx ty:: AdtDef ,
864
+ substs : & ' tcx Substs < ' tcx > ,
862
865
target : BasicBlock ,
863
866
unwind : Unwind ,
864
867
) -> BasicBlock {
865
- let block = self . unelaborated_free_block ( ty , target, unwind) ;
868
+ let block = self . unelaborated_free_block ( adt , substs , target, unwind) ;
866
869
self . drop_flag_test_block ( block, target, unwind)
867
870
}
868
871
869
872
fn unelaborated_free_block < ' a > (
870
873
& mut self ,
871
- ty : Ty < ' tcx > ,
874
+ adt : & ' tcx ty:: AdtDef ,
875
+ substs : & ' tcx Substs < ' tcx > ,
872
876
target : BasicBlock ,
873
877
unwind : Unwind
874
878
) -> BasicBlock {
875
879
let tcx = self . tcx ( ) ;
876
880
let unit_temp = Place :: Local ( self . new_temp ( tcx. mk_nil ( ) ) ) ;
877
881
let free_func = tcx. require_lang_item ( lang_items:: BoxFreeFnLangItem ) ;
878
- let substs = tcx. mk_substs ( iter:: once ( Kind :: from ( ty) ) ) ;
879
- let ref_ty = tcx. mk_ref ( tcx. types . re_erased , ty:: TypeAndMut {
880
- ty : ty,
881
- mutbl : hir:: Mutability :: MutMutable
882
- } ) ;
883
- let ptr_ty = tcx. mk_mut_ptr ( ty) ;
884
- let ref_tmp = Place :: Local ( self . new_temp ( ref_ty) ) ;
885
- let ptr_tmp = Place :: Local ( self . new_temp ( ptr_ty) ) ;
886
-
887
- let free_block = BasicBlockData {
888
- statements : vec ! [
882
+ let free_sig = tcx. fn_sig ( free_func) . skip_binder ( ) . clone ( ) ;
883
+ let free_inputs = free_sig. inputs ( ) ;
884
+ // If the box_free function takes a *mut T, transform the Box into
885
+ // such a pointer before calling box_free. Otherwise, pass it all
886
+ // the fields in the Box as individual arguments.
887
+ let ( stmts, args) = if free_inputs. len ( ) == 1 && free_inputs[ 0 ] . is_mutable_pointer ( ) {
888
+ let ty = substs. type_at ( 0 ) ;
889
+ let ref_ty = tcx. mk_ref ( tcx. types . re_erased , ty:: TypeAndMut {
890
+ ty : ty,
891
+ mutbl : hir:: Mutability :: MutMutable
892
+ } ) ;
893
+ let ptr_ty = tcx. mk_mut_ptr ( ty) ;
894
+ let ref_tmp = Place :: Local ( self . new_temp ( ref_ty) ) ;
895
+ let ptr_tmp = Place :: Local ( self . new_temp ( ptr_ty) ) ;
896
+ let stmts = vec ! [
889
897
self . assign( & ref_tmp, Rvalue :: Ref (
890
898
tcx. types. re_erased,
891
899
BorrowKind :: Mut { allow_two_phase_borrow: false } ,
@@ -896,11 +904,23 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
896
904
Operand :: Move ( ref_tmp) ,
897
905
ptr_ty,
898
906
) ) ,
899
- ] ,
907
+ ] ;
908
+ ( stmts, vec ! [ Operand :: Move ( ptr_tmp) ] )
909
+ } else {
910
+ let args = adt. variants [ 0 ] . fields . iter ( ) . enumerate ( ) . map ( |( i, f) | {
911
+ let field = Field :: new ( i) ;
912
+ let field_ty = f. ty ( self . tcx ( ) , substs) ;
913
+ Operand :: Move ( self . place . clone ( ) . field ( field, field_ty) )
914
+ } ) . collect ( ) ;
915
+ ( vec ! [ ] , args)
916
+ } ;
917
+
918
+ let free_block = BasicBlockData {
919
+ statements : stmts,
900
920
terminator : Some ( Terminator {
901
921
kind : TerminatorKind :: Call {
902
922
func : Operand :: function_handle ( tcx, free_func, substs, self . source_info . span ) ,
903
- args : vec ! [ Operand :: Move ( ptr_tmp ) ] ,
923
+ args : args ,
904
924
destination : Some ( ( unit_temp, target) ) ,
905
925
cleanup : None
906
926
} , // FIXME(#43234)
0 commit comments