@@ -10,7 +10,7 @@ use rustc::ty::util::IntTypeExt;
1010use rustc_data_structures:: indexed_vec:: Idx ;
1111use crate :: util:: patch:: MirPatch ;
1212
13- use std:: u32 ;
13+ use std:: convert :: TryInto ;
1414
1515#[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
1616pub enum DropFlagState {
@@ -545,10 +545,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
545545 self . elaborator . patch ( ) . new_block ( result)
546546 }
547547
548- /// create a loop that drops an array:
549- ///
550-
548+ /// Create a loop that drops an array:
551549 ///
550+ /// ```text
552551 /// loop-block:
553552 /// can_go = cur == length_or_end
554553 /// if can_go then succ else drop-block
@@ -561,15 +560,16 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
561560 /// cur = cur + 1
562561 /// }
563562 /// drop(ptr)
564- fn drop_loop ( & mut self ,
565- succ : BasicBlock ,
566- cur : Local ,
567- length_or_end : & Place < ' tcx > ,
568- ety : Ty < ' tcx > ,
569- unwind : Unwind ,
570- ptr_based : bool )
571- -> BasicBlock
572- {
563+ /// ```
564+ fn drop_loop (
565+ & mut self ,
566+ succ : BasicBlock ,
567+ cur : Local ,
568+ length_or_end : & Place < ' tcx > ,
569+ ety : Ty < ' tcx > ,
570+ unwind : Unwind ,
571+ ptr_based : bool ,
572+ ) -> BasicBlock {
573573 let copy = |place : & Place < ' tcx > | Operand :: Copy ( place. clone ( ) ) ;
574574 let move_ = |place : & Place < ' tcx > | Operand :: Move ( place. clone ( ) ) ;
575575 let tcx = self . tcx ( ) ;
@@ -591,13 +591,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
591591 elem : ProjectionElem :: Deref ,
592592 } ) )
593593 ) ,
594- Rvalue :: BinaryOp ( BinOp :: Offset , copy ( & Place :: Base ( PlaceBase :: Local ( cur) ) ) , one) )
594+ Rvalue :: BinaryOp ( BinOp :: Offset , move_ ( & Place :: Base ( PlaceBase :: Local ( cur) ) ) , one) )
595595 } else {
596596 ( Rvalue :: Ref (
597597 tcx. lifetimes . re_erased ,
598598 BorrowKind :: Mut { allow_two_phase_borrow : false } ,
599599 self . place . clone ( ) . index ( cur) ) ,
600- Rvalue :: BinaryOp ( BinOp :: Add , copy ( & Place :: Base ( PlaceBase :: Local ( cur) ) ) , one) )
600+ Rvalue :: BinaryOp ( BinOp :: Add , move_ ( & Place :: Base ( PlaceBase :: Local ( cur) ) ) , one) )
601601 } ;
602602
603603 let drop_block = BasicBlockData {
@@ -647,9 +647,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
647647 // }
648648
649649 if let Some ( size) = opt_size {
650- assert ! ( size <= ( u32 :: MAX as u64 ) ,
651- "move out check doesn 't implemented for array bigger then u32" ) ;
652- let size = size as u32 ;
650+ let size: u32 = size . try_into ( ) . unwrap_or_else ( |_| {
651+ bug ! ( "move out check isn 't implemented for array sizes bigger than u32::MAX " ) ;
652+ } ) ;
653653 let fields: Vec < ( Place < ' tcx > , Option < D :: Path > ) > = ( 0 ..size) . map ( |i| {
654654 ( self . place . clone ( ) . elem ( ProjectionElem :: ConstantIndex {
655655 offset : i,
@@ -667,33 +667,42 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
667667
668668 let move_ = |place : & Place < ' tcx > | Operand :: Move ( place. clone ( ) ) ;
669669 let tcx = self . tcx ( ) ;
670- let size = & Place :: Base ( PlaceBase :: Local ( self . new_temp ( tcx. types . usize ) ) ) ;
671- let size_is_zero = & Place :: Base ( PlaceBase :: Local ( self . new_temp ( tcx. types . bool ) ) ) ;
670+ let elem_size = & Place :: Base ( PlaceBase :: Local ( self . new_temp ( tcx. types . usize ) ) ) ;
671+ let len = & Place :: Base ( PlaceBase :: Local ( self . new_temp ( tcx. types . usize ) ) ) ;
672+
673+ static USIZE_SWITCH_ZERO : & [ u128 ] = & [ 0 ] ;
674+
672675 let base_block = BasicBlockData {
673676 statements : vec ! [
674- self . assign( size, Rvalue :: NullaryOp ( NullOp :: SizeOf , ety) ) ,
675- self . assign( size_is_zero, Rvalue :: BinaryOp ( BinOp :: Eq ,
676- move_( size) ,
677- self . constant_usize( 0 ) ) )
677+ self . assign( elem_size, Rvalue :: NullaryOp ( NullOp :: SizeOf , ety) ) ,
678+ self . assign( len, Rvalue :: Len ( self . place. clone( ) ) ) ,
678679 ] ,
679680 is_cleanup : self . unwind . is_cleanup ( ) ,
680681 terminator : Some ( Terminator {
681682 source_info : self . source_info ,
682- kind : TerminatorKind :: if_ (
683- tcx,
684- move_ ( size_is_zero) ,
685- self . drop_loop_pair ( ety, false ) ,
686- self . drop_loop_pair ( ety, true )
687- )
683+ kind : TerminatorKind :: SwitchInt {
684+ discr : move_ ( elem_size) ,
685+ switch_ty : tcx. types . usize ,
686+ values : From :: from ( USIZE_SWITCH_ZERO ) ,
687+ targets : vec ! [
688+ self . drop_loop_pair( ety, false , len. clone( ) ) ,
689+ self . drop_loop_pair( ety, true , len. clone( ) ) ,
690+ ] ,
691+ } ,
688692 } )
689693 } ;
690694 self . elaborator . patch ( ) . new_block ( base_block)
691695 }
692696
693- // create a pair of drop-loops of `place`, which drops its contents
694- // even in the case of 1 panic. If `ptr_based`, create a pointer loop,
695- // otherwise create an index loop.
696- fn drop_loop_pair ( & mut self , ety : Ty < ' tcx > , ptr_based : bool ) -> BasicBlock {
697+ /// Ceates a pair of drop-loops of `place`, which drops its contents, even
698+ /// in the case of 1 panic. If `ptr_based`, creates a pointer loop,
699+ /// otherwise create an index loop.
700+ fn drop_loop_pair (
701+ & mut self ,
702+ ety : Ty < ' tcx > ,
703+ ptr_based : bool ,
704+ length : Place < ' tcx > ,
705+ ) -> BasicBlock {
697706 debug ! ( "drop_loop_pair({:?}, {:?})" , ety, ptr_based) ;
698707 let tcx = self . tcx ( ) ;
699708 let iter_ty = if ptr_based {
@@ -703,7 +712,6 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
703712 } ;
704713
705714 let cur = self . new_temp ( iter_ty) ;
706- let length = Place :: Base ( PlaceBase :: Local ( self . new_temp ( tcx. types . usize ) ) ) ;
707715 let length_or_end = if ptr_based {
708716 // FIXME check if we want to make it return a `Place` directly
709717 // if all use sites want a `Place::Base` anyway.
@@ -722,41 +730,41 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
722730 ptr_based)
723731 } ) ;
724732
725- let succ = self . succ ; // FIXME(#43234)
726733 let loop_block = self . drop_loop (
727- succ,
734+ self . succ ,
728735 cur,
729736 & length_or_end,
730737 ety,
731738 unwind,
732739 ptr_based) ;
733740
734741 let cur = Place :: Base ( PlaceBase :: Local ( cur) ) ;
735- let zero = self . constant_usize ( 0 ) ;
736- let mut drop_block_stmts = vec ! [ ] ;
737- drop_block_stmts. push ( self . assign ( & length, Rvalue :: Len ( self . place . clone ( ) ) ) ) ;
738- if ptr_based {
742+ let drop_block_stmts = if ptr_based {
739743 let tmp_ty = tcx. mk_mut_ptr ( self . place_ty ( self . place ) ) ;
740744 let tmp = Place :: Base ( PlaceBase :: Local ( self . new_temp ( tmp_ty) ) ) ;
741745 // tmp = &mut P;
742746 // cur = tmp as *mut T;
743747 // end = Offset(cur, len);
744- drop_block_stmts. push ( self . assign ( & tmp, Rvalue :: Ref (
745- tcx. lifetimes . re_erased ,
746- BorrowKind :: Mut { allow_two_phase_borrow : false } ,
747- self . place . clone ( )
748- ) ) ) ;
749- drop_block_stmts. push ( self . assign ( & cur, Rvalue :: Cast (
750- CastKind :: Misc , Operand :: Move ( tmp) , iter_ty
751- ) ) ) ;
752- drop_block_stmts. push ( self . assign ( & length_or_end,
753- Rvalue :: BinaryOp ( BinOp :: Offset ,
754- Operand :: Copy ( cur) , Operand :: Move ( length)
755- ) ) ) ;
748+ vec ! [
749+ self . assign( & tmp, Rvalue :: Ref (
750+ tcx. lifetimes. re_erased,
751+ BorrowKind :: Mut { allow_two_phase_borrow: false } ,
752+ self . place. clone( )
753+ ) ) ,
754+ self . assign(
755+ & cur,
756+ Rvalue :: Cast ( CastKind :: Misc , Operand :: Move ( tmp) , iter_ty) ,
757+ ) ,
758+ self . assign(
759+ & length_or_end,
760+ Rvalue :: BinaryOp ( BinOp :: Offset , Operand :: Copy ( cur) , Operand :: Move ( length)
761+ ) ) ,
762+ ]
756763 } else {
757- // index = 0 (length already pushed)
758- drop_block_stmts. push ( self . assign ( & cur, Rvalue :: Use ( zero) ) ) ;
759- }
764+ // cur = 0 (length already pushed)
765+ let zero = self . constant_usize ( 0 ) ;
766+ vec ! [ self . assign( & cur, Rvalue :: Use ( zero) ) ]
767+ } ;
760768 let drop_block = self . elaborator . patch ( ) . new_block ( BasicBlockData {
761769 statements : drop_block_stmts,
762770 is_cleanup : unwind. is_cleanup ( ) ,
@@ -768,7 +776,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
768776
769777 // FIXME(#34708): handle partially-dropped array/slice elements.
770778 let reset_block = self . drop_flag_reset_block ( DropFlagMode :: Deep , drop_block, unwind) ;
771- self . drop_flag_test_block ( reset_block, succ, unwind)
779+ self . drop_flag_test_block ( reset_block, self . succ , unwind)
772780 }
773781
774782 /// The slow-path - create an "open", elaborated drop for a type
0 commit comments