1
1
use crate :: alloc:: { Allocator , Global } ;
2
2
use core:: fmt;
3
3
use core:: iter:: { FusedIterator , TrustedLen } ;
4
- use core:: mem:: { self , ManuallyDrop , SizedTypeProperties } ;
4
+ use core:: marker:: PhantomData ;
5
+ use core:: mem:: { ManuallyDrop , SizedTypeProperties } ;
5
6
use core:: ptr:: { self , NonNull } ;
6
7
use core:: slice:: { self } ;
7
8
@@ -29,14 +30,15 @@ pub struct Drain<
29
30
/// Length of tail
30
31
pub ( super ) tail_len : usize ,
31
32
/// Current remaining range to remove
32
- pub ( super ) iter : slice:: Iter < ' a , T > ,
33
+ pub ( super ) iter : slice:: DrainRaw < T > ,
33
34
pub ( super ) vec : NonNull < Vec < T , A > > ,
35
+ pub ( super ) phantom : PhantomData < & ' a [ T ] > ,
34
36
}
35
37
36
38
#[ stable( feature = "collection_debug" , since = "1.17.0" ) ]
37
39
impl < T : fmt:: Debug , A : Allocator > fmt:: Debug for Drain < ' _ , T , A > {
38
40
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 ( )
40
42
}
41
43
}
42
44
@@ -55,7 +57,9 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> {
55
57
#[ must_use]
56
58
#[ stable( feature = "vec_drain_as_slice" , since = "1.46.0" ) ]
57
59
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 ( ) }
59
63
}
60
64
61
65
/// Returns a reference to the underlying allocator.
@@ -108,8 +112,9 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> {
108
112
let start = source_vec. len ( ) ;
109
113
let tail = this. tail_start ;
110
114
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 ( ) ;
113
118
114
119
// ZSTs have no identity, so we don't need to move them around.
115
120
if !T :: IS_ZST {
@@ -154,7 +159,7 @@ impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
154
159
155
160
#[ inline]
156
161
fn next ( & mut self ) -> Option < T > {
157
- self . iter . next ( ) . map ( |elt| unsafe { ptr :: read ( elt as * const _ ) } )
162
+ self . iter . next ( )
158
163
}
159
164
160
165
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
@@ -166,7 +171,7 @@ impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
166
171
impl < T , A : Allocator > DoubleEndedIterator for Drain < ' _ , T , A > {
167
172
#[ inline]
168
173
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 ( )
170
175
}
171
176
}
172
177
@@ -195,16 +200,13 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
195
200
}
196
201
}
197
202
198
- let iter = mem:: take ( & mut self . iter ) ;
199
- let drop_len = iter. len ( ) ;
200
-
201
- let mut vec = self . vec ;
202
-
203
203
if T :: IS_ZST {
204
+ let drop_len = self . iter . forget_remaining ( ) . len ( ) ;
205
+
204
206
// ZSTs have no identity, so we don't need to move them around, we only need to drop the correct amount.
205
207
// this can be achieved by manipulating the Vec length instead of moving values out from `iter`.
206
208
unsafe {
207
- let vec = vec. as_mut ( ) ;
209
+ let vec = self . vec . as_mut ( ) ;
208
210
let old_len = vec. len ( ) ;
209
211
vec. set_len ( old_len + drop_len + self . tail_len ) ;
210
212
vec. truncate ( old_len + self . tail_len ) ;
@@ -214,28 +216,9 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
214
216
}
215
217
216
218
// 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 ) ;
218
220
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 ( ) ;
239
222
}
240
223
}
241
224
0 commit comments