@@ -19,7 +19,7 @@ use rustc::ty::util::IntTypeExt;
19
19
use rustc_data_structures:: indexed_vec:: Idx ;
20
20
use util:: patch:: MirPatch ;
21
21
22
- use std:: iter;
22
+ use std:: { iter, u32 } ;
23
23
24
24
#[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
25
25
pub enum DropFlagState {
@@ -95,6 +95,7 @@ pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug {
95
95
fn field_subpath ( & self , path : Self :: Path , field : Field ) -> Option < Self :: Path > ;
96
96
fn deref_subpath ( & self , path : Self :: Path ) -> Option < Self :: Path > ;
97
97
fn downcast_subpath ( & self , path : Self :: Path , variant : usize ) -> Option < Self :: Path > ;
98
+ fn array_subpath ( & self , path : Self :: Path , index : u32 , size : u32 ) -> Option < Self :: Path > ;
98
99
}
99
100
100
101
#[ derive( Debug ) ]
@@ -632,18 +633,36 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
632
633
loop_block
633
634
}
634
635
635
- fn open_drop_for_array ( & mut self , ety : Ty < ' tcx > ) -> BasicBlock {
636
- debug ! ( "open_drop_for_array({:?})" , ety) ;
636
+ fn open_drop_for_array ( & mut self , ety : Ty < ' tcx > , opt_size : Option < u64 > ) -> BasicBlock {
637
+ debug ! ( "open_drop_for_array({:?}, {:?} )" , ety, opt_size ) ;
637
638
638
639
// if size_of::<ety>() == 0 {
639
640
// index_based_loop
640
641
// } else {
641
642
// ptr_based_loop
642
643
// }
643
644
644
- let tcx = self . tcx ( ) ;
645
+ if let Some ( size) = opt_size {
646
+ assert ! ( size <= ( u32 :: MAX as u64 ) ,
647
+ "move out check doesn't implemented for array bigger then u32" ) ;
648
+ let size = size as u32 ;
649
+ let fields: Vec < ( Place < ' tcx > , Option < D :: Path > ) > = ( 0 ..size) . map ( |i| {
650
+ ( self . place . clone ( ) . elem ( ProjectionElem :: ConstantIndex {
651
+ offset : i,
652
+ min_length : size,
653
+ from_end : false
654
+ } ) ,
655
+ self . elaborator . array_subpath ( self . path , i, size) )
656
+ } ) . collect ( ) ;
657
+
658
+ if fields. iter ( ) . any ( |( _, path) | path. is_some ( ) ) {
659
+ let ( succ, unwind) = self . drop_ladder_bottom ( ) ;
660
+ return self . drop_ladder ( fields, succ, unwind) . 0
661
+ }
662
+ }
645
663
646
664
let move_ = |place : & Place < ' tcx > | Operand :: Move ( place. clone ( ) ) ;
665
+ let tcx = self . tcx ( ) ;
647
666
let size = & Place :: Local ( self . new_temp ( tcx. types . usize ) ) ;
648
667
let size_is_zero = & Place :: Local ( self . new_temp ( tcx. types . bool ) ) ;
649
668
let base_block = BasicBlockData {
@@ -779,9 +798,10 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
779
798
let succ = self . succ ;
780
799
self . complete_drop ( Some ( DropFlagMode :: Deep ) , succ, unwind)
781
800
}
782
- ty:: TyArray ( ety, _) | ty:: TySlice ( ety) => {
783
- self . open_drop_for_array ( ety)
784
- }
801
+ ty:: TyArray ( ety, size) => self . open_drop_for_array (
802
+ ety, size. val . to_const_int ( ) . and_then ( |v| v. to_u64 ( ) ) ) ,
803
+ ty:: TySlice ( ety) => self . open_drop_for_array ( ety, None ) ,
804
+
785
805
_ => bug ! ( "open drop from non-ADT `{:?}`" , ty)
786
806
}
787
807
}
0 commit comments