@@ -10,7 +10,7 @@ use rustc::ty::util::IntTypeExt;
10
10
use rustc_data_structures:: indexed_vec:: Idx ;
11
11
use crate :: util:: patch:: MirPatch ;
12
12
13
- use std:: u32 ;
13
+ use std:: convert :: TryInto ;
14
14
15
15
#[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
16
16
pub enum DropFlagState {
@@ -545,10 +545,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
545
545
self . elaborator . patch ( ) . new_block ( result)
546
546
}
547
547
548
- /// create a loop that drops an array:
549
- ///
550
-
548
+ /// Create a loop that drops an array:
551
549
///
550
+ /// ```text
552
551
/// loop-block:
553
552
/// can_go = cur == length_or_end
554
553
/// if can_go then succ else drop-block
@@ -561,15 +560,16 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
561
560
/// cur = cur + 1
562
561
/// }
563
562
/// 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 {
573
573
let copy = |place : & Place < ' tcx > | Operand :: Copy ( place. clone ( ) ) ;
574
574
let move_ = |place : & Place < ' tcx > | Operand :: Move ( place. clone ( ) ) ;
575
575
let tcx = self . tcx ( ) ;
@@ -591,13 +591,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
591
591
elem : ProjectionElem :: Deref ,
592
592
} ) )
593
593
) ,
594
- Rvalue :: BinaryOp ( BinOp :: Offset , copy ( & Place :: Base ( PlaceBase :: Local ( cur) ) ) , one) )
594
+ Rvalue :: BinaryOp ( BinOp :: Offset , move_ ( & Place :: Base ( PlaceBase :: Local ( cur) ) ) , one) )
595
595
} else {
596
596
( Rvalue :: Ref (
597
597
tcx. lifetimes . re_erased ,
598
598
BorrowKind :: Mut { allow_two_phase_borrow : false } ,
599
599
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) )
601
601
} ;
602
602
603
603
let drop_block = BasicBlockData {
@@ -647,9 +647,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
647
647
// }
648
648
649
649
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
+ } ) ;
653
653
let fields: Vec < ( Place < ' tcx > , Option < D :: Path > ) > = ( 0 ..size) . map ( |i| {
654
654
( self . place . clone ( ) . elem ( ProjectionElem :: ConstantIndex {
655
655
offset : i,
@@ -667,33 +667,42 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
667
667
668
668
let move_ = |place : & Place < ' tcx > | Operand :: Move ( place. clone ( ) ) ;
669
669
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
+
672
675
let base_block = BasicBlockData {
673
676
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( ) ) ) ,
678
679
] ,
679
680
is_cleanup : self . unwind . is_cleanup ( ) ,
680
681
terminator : Some ( Terminator {
681
682
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
+ } ,
688
692
} )
689
693
} ;
690
694
self . elaborator . patch ( ) . new_block ( base_block)
691
695
}
692
696
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 {
697
706
debug ! ( "drop_loop_pair({:?}, {:?})" , ety, ptr_based) ;
698
707
let tcx = self . tcx ( ) ;
699
708
let iter_ty = if ptr_based {
@@ -703,7 +712,6 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
703
712
} ;
704
713
705
714
let cur = self . new_temp ( iter_ty) ;
706
- let length = Place :: Base ( PlaceBase :: Local ( self . new_temp ( tcx. types . usize ) ) ) ;
707
715
let length_or_end = if ptr_based {
708
716
// FIXME check if we want to make it return a `Place` directly
709
717
// if all use sites want a `Place::Base` anyway.
@@ -722,41 +730,41 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
722
730
ptr_based)
723
731
} ) ;
724
732
725
- let succ = self . succ ; // FIXME(#43234)
726
733
let loop_block = self . drop_loop (
727
- succ,
734
+ self . succ ,
728
735
cur,
729
736
& length_or_end,
730
737
ety,
731
738
unwind,
732
739
ptr_based) ;
733
740
734
741
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 {
739
743
let tmp_ty = tcx. mk_mut_ptr ( self . place_ty ( self . place ) ) ;
740
744
let tmp = Place :: Base ( PlaceBase :: Local ( self . new_temp ( tmp_ty) ) ) ;
741
745
// tmp = &mut P;
742
746
// cur = tmp as *mut T;
743
747
// 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
+ ]
756
763
} 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
+ } ;
760
768
let drop_block = self . elaborator . patch ( ) . new_block ( BasicBlockData {
761
769
statements : drop_block_stmts,
762
770
is_cleanup : unwind. is_cleanup ( ) ,
@@ -768,7 +776,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
768
776
769
777
// FIXME(#34708): handle partially-dropped array/slice elements.
770
778
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)
772
780
}
773
781
774
782
/// The slow-path - create an "open", elaborated drop for a type
0 commit comments