1
- use std:: { fmt, iter} ;
1
+ use std:: { fmt, iter, mem } ;
2
2
3
3
use rustc_abi:: { FIRST_VARIANT , FieldIdx , VariantIdx } ;
4
4
use rustc_hir:: lang_items:: LangItem ;
5
5
use rustc_index:: Idx ;
6
6
use rustc_middle:: mir:: patch:: MirPatch ;
7
7
use rustc_middle:: mir:: * ;
8
8
use rustc_middle:: span_bug;
9
+ use rustc_middle:: ty:: adjustment:: PointerCoercion ;
9
10
use rustc_middle:: ty:: util:: IntTypeExt ;
10
11
use rustc_middle:: ty:: { self , GenericArgsRef , Ty , TyCtxt } ;
11
12
use rustc_span:: DUMMY_SP ;
@@ -738,8 +739,13 @@ where
738
739
loop_block
739
740
}
740
741
741
- fn open_drop_for_array ( & mut self , ety : Ty < ' tcx > , opt_size : Option < u64 > ) -> BasicBlock {
742
- debug ! ( "open_drop_for_array({:?}, {:?})" , ety, opt_size) ;
742
+ fn open_drop_for_array (
743
+ & mut self ,
744
+ array_ty : Ty < ' tcx > ,
745
+ ety : Ty < ' tcx > ,
746
+ opt_size : Option < u64 > ,
747
+ ) -> BasicBlock {
748
+ debug ! ( "open_drop_for_array({:?}, {:?}, {:?})" , array_ty, ety, opt_size) ;
743
749
let tcx = self . tcx ( ) ;
744
750
745
751
if let Some ( size) = opt_size {
@@ -801,13 +807,50 @@ where
801
807
}
802
808
}
803
809
804
- self . drop_loop_pair ( ety)
810
+ let array_ptr_ty = Ty :: new_mut_ptr ( tcx, array_ty) ;
811
+ let array_ptr = self . new_temp ( array_ptr_ty) ;
812
+
813
+ let slice_ty = Ty :: new_slice ( tcx, ety) ;
814
+ let slice_ptr_ty = Ty :: new_mut_ptr ( tcx, slice_ty) ;
815
+ let slice_ptr = self . new_temp ( slice_ptr_ty) ;
816
+
817
+ let mut delegate_block = BasicBlockData {
818
+ statements : vec ! [
819
+ self . assign( Place :: from( array_ptr) , Rvalue :: RawPtr ( Mutability :: Mut , self . place) ) ,
820
+ self . assign(
821
+ Place :: from( slice_ptr) ,
822
+ Rvalue :: Cast (
823
+ CastKind :: PointerCoercion (
824
+ PointerCoercion :: Unsize ,
825
+ CoercionSource :: Implicit ,
826
+ ) ,
827
+ Operand :: Move ( Place :: from( array_ptr) ) ,
828
+ slice_ptr_ty,
829
+ ) ,
830
+ ) ,
831
+ ] ,
832
+ is_cleanup : self . unwind . is_cleanup ( ) ,
833
+ terminator : None ,
834
+ } ;
835
+
836
+ let array_place = mem:: replace (
837
+ & mut self . place ,
838
+ Place :: from ( slice_ptr) . project_deeper ( & [ PlaceElem :: Deref ] , tcx) ,
839
+ ) ;
840
+ let slice_block = self . drop_loop_pair_for_slice ( ety) ;
841
+ self . place = array_place;
842
+
843
+ delegate_block. terminator = Some ( Terminator {
844
+ source_info : self . source_info ,
845
+ kind : TerminatorKind :: Goto { target : slice_block } ,
846
+ } ) ;
847
+ self . elaborator . patch ( ) . new_block ( delegate_block)
805
848
}
806
849
807
850
/// Creates a pair of drop-loops of `place`, which drops its contents, even
808
851
/// in the case of 1 panic.
809
- fn drop_loop_pair ( & mut self , ety : Ty < ' tcx > ) -> BasicBlock {
810
- debug ! ( "drop_loop_pair ({:?})" , ety) ;
852
+ fn drop_loop_pair_for_slice ( & mut self , ety : Ty < ' tcx > ) -> BasicBlock {
853
+ debug ! ( "drop_loop_pair_for_slice ({:?})" , ety) ;
811
854
let tcx = self . tcx ( ) ;
812
855
let len = self . new_temp ( tcx. types . usize ) ;
813
856
let cur = self . new_temp ( tcx. types . usize ) ;
@@ -817,10 +860,24 @@ where
817
860
818
861
let loop_block = self . drop_loop ( self . succ , cur, len, ety, unwind) ;
819
862
863
+ let [ PlaceElem :: Deref ] = self . place . projection . as_slice ( ) else {
864
+ span_bug ! (
865
+ self . source_info. span,
866
+ "Expected place for slice drop shim to be *_n, but it's {:?}" ,
867
+ self . place,
868
+ ) ;
869
+ } ;
870
+
820
871
let zero = self . constant_usize ( 0 ) ;
821
872
let block = BasicBlockData {
822
873
statements : vec ! [
823
- self . assign( len. into( ) , Rvalue :: Len ( self . place) ) ,
874
+ self . assign(
875
+ len. into( ) ,
876
+ Rvalue :: UnaryOp (
877
+ UnOp :: PtrMetadata ,
878
+ Operand :: Copy ( Place :: from( self . place. local) ) ,
879
+ ) ,
880
+ ) ,
824
881
self . assign( cur. into( ) , Rvalue :: Use ( zero) ) ,
825
882
] ,
826
883
is_cleanup : unwind. is_cleanup ( ) ,
@@ -863,9 +920,9 @@ where
863
920
ty:: Dynamic ( ..) => self . complete_drop ( self . succ , self . unwind ) ,
864
921
ty:: Array ( ety, size) => {
865
922
let size = size. try_to_target_usize ( self . tcx ( ) ) ;
866
- self . open_drop_for_array ( * ety, size)
923
+ self . open_drop_for_array ( ty , * ety, size)
867
924
}
868
- ty:: Slice ( ety) => self . drop_loop_pair ( * ety) ,
925
+ ty:: Slice ( ety) => self . drop_loop_pair_for_slice ( * ety) ,
869
926
870
927
_ => span_bug ! ( self . source_info. span, "open drop from non-ADT `{:?}`" , ty) ,
871
928
}
0 commit comments