11
11
use std:: fmt;
12
12
use rustc:: hir;
13
13
use rustc:: mir:: * ;
14
- use rustc:: middle:: const_val:: ConstInt ;
14
+ use rustc:: middle:: const_val:: { ConstInt , ConstVal } ;
15
15
use rustc:: middle:: lang_items;
16
16
use rustc:: ty:: { self , Ty } ;
17
17
use rustc:: ty:: subst:: { Kind , Substs } ;
@@ -535,6 +535,114 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
535
535
} )
536
536
}
537
537
538
+ /// create a loop that drops an array:
539
+ ///
540
+ /// loop-block:
541
+ /// can_go = index < len
542
+ /// if can_go then drop-block else succ
543
+ /// drop-block:
544
+ /// ptr = &mut LV[len]
545
+ /// index = index + 1
546
+ /// drop(ptr)
547
+ fn drop_loop ( & mut self ,
548
+ unwind : Option < BasicBlock > ,
549
+ succ : BasicBlock ,
550
+ index : & Lvalue < ' tcx > ,
551
+ length : & Lvalue < ' tcx > ,
552
+ ety : Ty < ' tcx > ,
553
+ is_cleanup : bool )
554
+ -> BasicBlock
555
+ {
556
+ let use_ = |lv : & Lvalue < ' tcx > | Operand :: Consume ( lv. clone ( ) ) ;
557
+ let tcx = self . tcx ( ) ;
558
+
559
+ let ref_ty = tcx. mk_ref ( tcx. types . re_erased , ty:: TypeAndMut {
560
+ ty : ety,
561
+ mutbl : hir:: Mutability :: MutMutable
562
+ } ) ;
563
+ let ptr = & Lvalue :: Local ( self . new_temp ( ref_ty) ) ;
564
+ let can_go = & Lvalue :: Local ( self . new_temp ( tcx. types . bool ) ) ;
565
+
566
+ let one = self . constant_usize ( 1 ) ;
567
+ let drop_block = self . elaborator . patch ( ) . new_block ( BasicBlockData {
568
+ statements : vec ! [
569
+ Statement { source_info: self . source_info, kind: StatementKind :: Assign (
570
+ ptr. clone( ) , Rvalue :: Ref (
571
+ tcx. types. re_erased, BorrowKind :: Mut ,
572
+ self . lvalue. clone( ) . index( use_( index) )
573
+ ) ,
574
+ ) } ,
575
+ Statement { source_info: self . source_info, kind: StatementKind :: Assign (
576
+ index. clone( ) , Rvalue :: BinaryOp ( BinOp :: Add , use_( index) , one)
577
+ ) } ,
578
+ ] ,
579
+ is_cleanup,
580
+ terminator : Some ( Terminator {
581
+ source_info : self . source_info ,
582
+ kind : TerminatorKind :: Resume ,
583
+ } )
584
+ } ) ;
585
+
586
+ let loop_block = self . elaborator . patch ( ) . new_block ( BasicBlockData {
587
+ statements : vec ! [
588
+ Statement { source_info: self . source_info, kind: StatementKind :: Assign (
589
+ can_go. clone( ) , Rvalue :: BinaryOp ( BinOp :: Lt , use_( index) , use_( length) )
590
+ ) } ,
591
+ ] ,
592
+ is_cleanup,
593
+ terminator : Some ( Terminator {
594
+ source_info : self . source_info ,
595
+ kind : TerminatorKind :: if_ ( tcx, use_ ( can_go) , drop_block, succ)
596
+ } )
597
+ } ) ;
598
+
599
+ self . elaborator . patch ( ) . patch_terminator ( drop_block, TerminatorKind :: Drop {
600
+ location : ptr. clone ( ) . deref ( ) ,
601
+ target : loop_block,
602
+ unwind : unwind
603
+ } ) ;
604
+
605
+ loop_block
606
+ }
607
+
608
+ fn open_drop_for_array ( & mut self , ety : Ty < ' tcx > ) -> BasicBlock {
609
+ debug ! ( "open_drop_for_array({:?})" , ety) ;
610
+ // FIXME: using an index instead of a pointer to avoid
611
+ // special-casing ZSTs.
612
+ let tcx = self . tcx ( ) ;
613
+ let index = & Lvalue :: Local ( self . new_temp ( tcx. types . usize ) ) ;
614
+ let length = & Lvalue :: Local ( self . new_temp ( tcx. types . usize ) ) ;
615
+
616
+ let unwind = self . unwind . map ( |unwind| {
617
+ self . drop_loop ( None , unwind, index, length, ety, true )
618
+ } ) ;
619
+
620
+ let is_cleanup = self . is_cleanup ;
621
+ let succ = self . succ ; // FIXME(#6393)
622
+ let loop_block = self . drop_loop ( unwind, succ, index, length, ety, is_cleanup) ;
623
+
624
+ let zero = self . constant_usize ( 0 ) ;
625
+ let drop_block = self . elaborator . patch ( ) . new_block ( BasicBlockData {
626
+ statements : vec ! [
627
+ Statement { source_info: self . source_info, kind: StatementKind :: Assign (
628
+ length. clone( ) , Rvalue :: Len ( self . lvalue. clone( ) )
629
+ ) } ,
630
+ Statement { source_info: self . source_info, kind: StatementKind :: Assign (
631
+ index. clone( ) , Rvalue :: Use ( zero) ,
632
+ ) } ,
633
+ ] ,
634
+ is_cleanup,
635
+ terminator : Some ( Terminator {
636
+ source_info : self . source_info ,
637
+ kind : TerminatorKind :: Goto { target : loop_block }
638
+ } )
639
+ } ) ;
640
+
641
+ // FIXME(#34708): handle partially-dropped array/slice elements.
642
+ self . drop_flag_test_and_reset_block (
643
+ is_cleanup, Some ( DropFlagMode :: Deep ) , drop_block, succ)
644
+ }
645
+
538
646
/// The slow-path - create an "open", elaborated drop for a type
539
647
/// which is moved-out-of only partially, and patch `bb` to a jump
540
648
/// to it. This must not be called on ADTs with a destructor,
@@ -564,10 +672,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
564
672
ty:: TyDynamic ( ..) => {
565
673
self . complete_drop ( is_cleanup, Some ( DropFlagMode :: Deep ) , succ)
566
674
}
567
- ty:: TyArray ( ..) | ty:: TySlice ( ..) => {
568
- // FIXME(#34708): handle partially-dropped
569
- // array/slice elements.
570
- self . complete_drop ( is_cleanup, Some ( DropFlagMode :: Deep ) , succ)
675
+ ty:: TyArray ( ety, _) | ty:: TySlice ( ety) => {
676
+ self . open_drop_for_array ( ety)
571
677
}
572
678
_ => bug ! ( "open drop from non-ADT `{:?}`" , ty)
573
679
}
@@ -588,6 +694,17 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
588
694
debug ! ( "complete_drop({:?},{:?})" , self , drop_mode) ;
589
695
590
696
let drop_block = self . drop_block ( is_cleanup, succ) ;
697
+ self . drop_flag_test_and_reset_block ( is_cleanup, drop_mode, drop_block, succ)
698
+ }
699
+
700
+ fn drop_flag_test_and_reset_block ( & mut self ,
701
+ is_cleanup : bool ,
702
+ drop_mode : Option < DropFlagMode > ,
703
+ drop_block : BasicBlock ,
704
+ succ : BasicBlock ) -> BasicBlock
705
+ {
706
+ debug ! ( "drop_flag_test_and_reset_block({:?},{:?})" , self , drop_mode) ;
707
+
591
708
if let Some ( mode) = drop_mode {
592
709
let block_start = Location { block : drop_block, statement_index : 0 } ;
593
710
self . elaborator . clear_drop_flag ( block_start, self . path , mode) ;
@@ -691,4 +808,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
691
808
let mir = self . elaborator . mir ( ) ;
692
809
self . elaborator . patch ( ) . terminator_loc ( mir, bb)
693
810
}
811
+
812
+ fn constant_usize ( & self , val : usize ) -> Operand < ' tcx > {
813
+ Operand :: Constant ( box Constant {
814
+ span : self . source_info . span ,
815
+ ty : self . tcx ( ) . types . usize ,
816
+ literal : Literal :: Value { value : ConstVal :: Integral ( self . tcx ( ) . const_usize ( val) ) }
817
+ } )
818
+ }
694
819
}
0 commit comments