@@ -337,18 +337,19 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
337337 self . drop_ladder ( fields, succ, unwind) . 0
338338 }
339339
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
341342 {
342- debug ! ( "open_drop_for_box({:?}, {:?})" , self , ty ) ;
343+ debug ! ( "open_drop_for_box({:?}, {:?}, {:?} )" , self , adt , substs ) ;
343344
344345 let interior = self . place . clone ( ) . deref ( ) ;
345346 let interior_path = self . elaborator . deref_subpath ( self . path ) ;
346347
347348 let succ = self . succ ; // FIXME(#43234)
348349 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) ;
350351 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 )
352353 } ) ;
353354
354355 self . drop_subpath ( & interior, interior_path, succ, unwind_succ)
@@ -791,11 +792,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
791792 ty:: TyTuple ( tys) => {
792793 self . open_drop_for_tuple ( tys)
793794 }
794- ty:: TyAdt ( def, _) if def. is_box ( ) => {
795- self . open_drop_for_box ( ty. boxed_ty ( ) )
796- }
797795 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+ }
799801 }
800802 ty:: TyDynamic ( ..) => {
801803 let unwind = self . unwind ; // FIXME(#43234)
@@ -858,34 +860,40 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
858860
859861 fn box_free_block < ' a > (
860862 & mut self ,
861- ty : Ty < ' tcx > ,
863+ adt : & ' tcx ty:: AdtDef ,
864+ substs : & ' tcx Substs < ' tcx > ,
862865 target : BasicBlock ,
863866 unwind : Unwind ,
864867 ) -> BasicBlock {
865- let block = self . unelaborated_free_block ( ty , target, unwind) ;
868+ let block = self . unelaborated_free_block ( adt , substs , target, unwind) ;
866869 self . drop_flag_test_block ( block, target, unwind)
867870 }
868871
869872 fn unelaborated_free_block < ' a > (
870873 & mut self ,
871- ty : Ty < ' tcx > ,
874+ adt : & ' tcx ty:: AdtDef ,
875+ substs : & ' tcx Substs < ' tcx > ,
872876 target : BasicBlock ,
873877 unwind : Unwind
874878 ) -> BasicBlock {
875879 let tcx = self . tcx ( ) ;
876880 let unit_temp = Place :: Local ( self . new_temp ( tcx. mk_nil ( ) ) ) ;
877881 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 ! [
889897 self . assign( & ref_tmp, Rvalue :: Ref (
890898 tcx. types. re_erased,
891899 BorrowKind :: Mut { allow_two_phase_borrow: false } ,
@@ -896,11 +904,23 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
896904 Operand :: Move ( ref_tmp) ,
897905 ptr_ty,
898906 ) ) ,
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,
900920 terminator : Some ( Terminator {
901921 kind : TerminatorKind :: Call {
902922 func : Operand :: function_handle ( tcx, free_func, substs, self . source_info . span ) ,
903- args : vec ! [ Operand :: Move ( ptr_tmp ) ] ,
923+ args : args ,
904924 destination : Some ( ( unit_temp, target) ) ,
905925 cleanup : None
906926 } , // FIXME(#43234)
0 commit comments