11use crate :: alloc:: { Allocator , Global } ;
22use core:: fmt;
33use core:: iter:: { FusedIterator , TrustedLen } ;
4- use core:: mem:: { self , ManuallyDrop , SizedTypeProperties } ;
4+ use core:: marker:: PhantomData ;
5+ use core:: mem:: { ManuallyDrop , SizedTypeProperties } ;
56use core:: ptr:: { self , NonNull } ;
67use core:: slice:: { self } ;
78
@@ -29,14 +30,15 @@ pub struct Drain<
2930 /// Length of tail
3031 pub ( super ) tail_len : usize ,
3132 /// Current remaining range to remove
32- pub ( super ) iter : slice:: Iter < ' a , T > ,
33+ pub ( super ) iter : slice:: DrainRaw < T > ,
3334 pub ( super ) vec : NonNull < Vec < T , A > > ,
35+ pub ( super ) phantom : PhantomData < & ' a [ T ] > ,
3436}
3537
3638#[ stable( feature = "collection_debug" , since = "1.17.0" ) ]
3739impl < T : fmt:: Debug , A : Allocator > fmt:: Debug for Drain < ' _ , T , A > {
3840 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
39- f. debug_tuple ( "Drain" ) . field ( & self . iter . as_slice ( ) ) . finish ( )
41+ f. debug_tuple ( "Drain" ) . field ( & self . as_slice ( ) ) . finish ( )
4042 }
4143}
4244
@@ -55,7 +57,9 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> {
5557 #[ must_use]
5658 #[ stable( feature = "vec_drain_as_slice" , since = "1.46.0" ) ]
5759 pub fn as_slice ( & self ) -> & [ T ] {
58- self . iter . as_slice ( )
60+ // SAFETY: Restricting the lifetime of the returned slice to the self
61+ // borrow keeps anything else from dropping them.
62+ unsafe { self . iter . as_nonnull_slice ( ) . as_ref ( ) }
5963 }
6064
6165 /// Returns a reference to the underlying allocator.
@@ -108,8 +112,9 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> {
108112 let start = source_vec. len ( ) ;
109113 let tail = this. tail_start ;
110114
111- let unyielded_len = this. iter . len ( ) ;
112- let unyielded_ptr = this. iter . as_slice ( ) . as_ptr ( ) ;
115+ let keep_items = this. iter . forget_remaining ( ) ;
116+ let unyielded_len = keep_items. len ( ) ;
117+ let unyielded_ptr = keep_items. as_mut_ptr ( ) ;
113118
114119 // ZSTs have no identity, so we don't need to move them around.
115120 if !T :: IS_ZST {
@@ -154,7 +159,7 @@ impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
154159
155160 #[ inline]
156161 fn next ( & mut self ) -> Option < T > {
157- self . iter . next ( ) . map ( |elt| unsafe { ptr :: read ( elt as * const _ ) } )
162+ self . iter . next ( )
158163 }
159164
160165 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
@@ -166,7 +171,7 @@ impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
166171impl < T , A : Allocator > DoubleEndedIterator for Drain < ' _ , T , A > {
167172 #[ inline]
168173 fn next_back ( & mut self ) -> Option < T > {
169- self . iter . next_back ( ) . map ( |elt| unsafe { ptr :: read ( elt as * const _ ) } )
174+ self . iter . next_back ( )
170175 }
171176}
172177
@@ -195,16 +200,13 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
195200 }
196201 }
197202
198- let iter = mem:: take ( & mut self . iter ) ;
199- let drop_len = iter. len ( ) ;
200-
201- let mut vec = self . vec ;
202-
203203 if T :: IS_ZST {
204+ let drop_len = self . iter . forget_remaining ( ) . len ( ) ;
205+
204206 // ZSTs have no identity, so we don't need to move them around, we only need to drop the correct amount.
205207 // this can be achieved by manipulating the Vec length instead of moving values out from `iter`.
206208 unsafe {
207- let vec = vec. as_mut ( ) ;
209+ let vec = self . vec . as_mut ( ) ;
208210 let old_len = vec. len ( ) ;
209211 vec. set_len ( old_len + drop_len + self . tail_len ) ;
210212 vec. truncate ( old_len + self . tail_len ) ;
@@ -214,28 +216,9 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
214216 }
215217
216218 // ensure elements are moved back into their appropriate places, even when drop_in_place panics
217- let _guard = DropGuard ( self ) ;
219+ let guard = DropGuard ( self ) ;
218220
219- if drop_len == 0 {
220- return ;
221- }
222-
223- // as_slice() must only be called when iter.len() is > 0 because
224- // it also gets touched by vec::Splice which may turn it into a dangling pointer
225- // which would make it and the vec pointer point to different allocations which would
226- // lead to invalid pointer arithmetic below.
227- let drop_ptr = iter. as_slice ( ) . as_ptr ( ) ;
228-
229- unsafe {
230- // drop_ptr comes from a slice::Iter which only gives us a &[T] but for drop_in_place
231- // a pointer with mutable provenance is necessary. Therefore we must reconstruct
232- // it from the original vec but also avoid creating a &mut to the front since that could
233- // invalidate raw pointers to it which some unsafe code might rely on.
234- let vec_ptr = vec. as_mut ( ) . as_mut_ptr ( ) ;
235- let drop_offset = drop_ptr. sub_ptr ( vec_ptr) ;
236- let to_drop = ptr:: slice_from_raw_parts_mut ( vec_ptr. add ( drop_offset) , drop_len) ;
237- ptr:: drop_in_place ( to_drop) ;
238- }
221+ guard. 0 . iter . drop_remaining ( ) ;
239222 }
240223}
241224
0 commit comments