@@ -19,7 +19,7 @@ use rustc::ty::util::IntTypeExt;
1919use rustc_data_structures:: indexed_vec:: Idx ;
2020use util:: patch:: MirPatch ;
2121
22- use std:: iter;
22+ use std:: { iter, u32 } ;
2323
2424#[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
2525pub enum DropFlagState {
@@ -95,6 +95,7 @@ pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug {
9595 fn field_subpath ( & self , path : Self :: Path , field : Field ) -> Option < Self :: Path > ;
9696 fn deref_subpath ( & self , path : Self :: Path ) -> Option < Self :: Path > ;
9797 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 > ;
9899}
99100
100101#[ derive( Debug ) ]
@@ -632,18 +633,36 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
632633 loop_block
633634 }
634635
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 ) ;
637638
638639 // if size_of::<ety>() == 0 {
639640 // index_based_loop
640641 // } else {
641642 // ptr_based_loop
642643 // }
643644
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+ }
645663
646664 let move_ = |place : & Place < ' tcx > | Operand :: Move ( place. clone ( ) ) ;
665+ let tcx = self . tcx ( ) ;
647666 let size = & Place :: Local ( self . new_temp ( tcx. types . usize ) ) ;
648667 let size_is_zero = & Place :: Local ( self . new_temp ( tcx. types . bool ) ) ;
649668 let base_block = BasicBlockData {
@@ -779,9 +798,10 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
779798 let succ = self . succ ;
780799 self . complete_drop ( Some ( DropFlagMode :: Deep ) , succ, unwind)
781800 }
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+
785805 _ => bug ! ( "open drop from non-ADT `{:?}`" , ty)
786806 }
787807 }
0 commit comments