1
1
//! Defines the `IntoIter` owned iterator for arrays.
2
2
3
3
use crate :: {
4
- cmp , fmt,
4
+ fmt,
5
5
iter:: { self , ExactSizeIterator , FusedIterator , TrustedLen } ,
6
6
mem:: { self , MaybeUninit } ,
7
- ops:: Range ,
7
+ ops:: { IndexRange , Range } ,
8
8
ptr,
9
9
} ;
10
10
@@ -29,9 +29,10 @@ pub struct IntoIter<T, const N: usize> {
29
29
/// The elements in `data` that have not been yielded yet.
30
30
///
31
31
/// Invariants:
32
- /// - `alive.start <= alive.end`
33
32
/// - `alive.end <= N`
34
- alive : Range < usize > ,
33
+ ///
34
+ /// (And the `IndexRange` type requires `alive.start <= alive.end`.)
35
+ alive : IndexRange ,
35
36
}
36
37
37
38
// Note: the `#[rustc_skip_array_during_method_dispatch]` on `trait IntoIterator`
@@ -69,7 +70,7 @@ impl<T, const N: usize> IntoIterator for [T; N] {
69
70
// Until then, we can use `mem::transmute_copy` to create a bitwise copy
70
71
// as a different type, then forget `array` so that it is not dropped.
71
72
unsafe {
72
- let iter = IntoIter { data : mem:: transmute_copy ( & self ) , alive : 0 .. N } ;
73
+ let iter = IntoIter { data : mem:: transmute_copy ( & self ) , alive : IndexRange :: zero_to ( N ) } ;
73
74
mem:: forget ( self ) ;
74
75
iter
75
76
}
@@ -147,7 +148,9 @@ impl<T, const N: usize> IntoIter<T, N> {
147
148
buffer : [ MaybeUninit < T > ; N ] ,
148
149
initialized : Range < usize > ,
149
150
) -> Self {
150
- Self { data : buffer, alive : initialized }
151
+ // SAFETY: one of our safety conditions is that the range is canonical.
152
+ let alive = unsafe { IndexRange :: new_unchecked ( initialized. start , initialized. end ) } ;
153
+ Self { data : buffer, alive }
151
154
}
152
155
153
156
/// Creates an iterator over `T` which returns no elements.
@@ -283,24 +286,19 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
283
286
}
284
287
285
288
fn advance_by ( & mut self , n : usize ) -> Result < ( ) , usize > {
286
- let len = self . len ( ) ;
287
-
288
- // The number of elements to drop. Always in-bounds by construction.
289
- let delta = cmp:: min ( n, len) ;
290
-
291
- let range_to_drop = self . alive . start ..( self . alive . start + delta) ;
289
+ let original_len = self . len ( ) ;
292
290
293
- // Moving the start marks them as conceptually "dropped", so if anything
294
- // goes bad then our drop impl won't double-free them.
295
- self . alive . start += delta ;
291
+ // This also moves the start, which marks them as conceptually "dropped",
292
+ // so if anything goes bad then our drop impl won't double-free them.
293
+ let range_to_drop = self . alive . take_prefix ( n ) ;
296
294
297
295
// SAFETY: These elements are currently initialized, so it's fine to drop them.
298
296
unsafe {
299
297
let slice = self . data . get_unchecked_mut ( range_to_drop) ;
300
298
ptr:: drop_in_place ( MaybeUninit :: slice_assume_init_mut ( slice) ) ;
301
299
}
302
300
303
- if n > len { Err ( len ) } else { Ok ( ( ) ) }
301
+ if n > original_len { Err ( original_len ) } else { Ok ( ( ) ) }
304
302
}
305
303
}
306
304
@@ -338,24 +336,19 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
338
336
}
339
337
340
338
fn advance_back_by ( & mut self , n : usize ) -> Result < ( ) , usize > {
341
- let len = self . len ( ) ;
342
-
343
- // The number of elements to drop. Always in-bounds by construction.
344
- let delta = cmp:: min ( n, len) ;
345
-
346
- let range_to_drop = ( self . alive . end - delta) ..self . alive . end ;
339
+ let original_len = self . len ( ) ;
347
340
348
- // Moving the end marks them as conceptually "dropped", so if anything
349
- // goes bad then our drop impl won't double-free them.
350
- self . alive . end -= delta ;
341
+ // This also moves the end, which marks them as conceptually "dropped",
342
+ // so if anything goes bad then our drop impl won't double-free them.
343
+ let range_to_drop = self . alive . take_suffix ( n ) ;
351
344
352
345
// SAFETY: These elements are currently initialized, so it's fine to drop them.
353
346
unsafe {
354
347
let slice = self . data . get_unchecked_mut ( range_to_drop) ;
355
348
ptr:: drop_in_place ( MaybeUninit :: slice_assume_init_mut ( slice) ) ;
356
349
}
357
350
358
- if n > len { Err ( len ) } else { Ok ( ( ) ) }
351
+ if n > original_len { Err ( original_len ) } else { Ok ( ( ) ) }
359
352
}
360
353
}
361
354
@@ -372,9 +365,7 @@ impl<T, const N: usize> Drop for IntoIter<T, N> {
372
365
#[ stable( feature = "array_value_iter_impls" , since = "1.40.0" ) ]
373
366
impl < T , const N : usize > ExactSizeIterator for IntoIter < T , N > {
374
367
fn len ( & self ) -> usize {
375
- // Will never underflow due to the invariant `alive.start <=
376
- // alive.end`.
377
- self . alive . end - self . alive . start
368
+ self . alive . len ( )
378
369
}
379
370
fn is_empty ( & self ) -> bool {
380
371
self . alive . is_empty ( )
@@ -396,14 +387,15 @@ impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
396
387
fn clone ( & self ) -> Self {
397
388
// Note, we don't really need to match the exact same alive range, so
398
389
// we can just clone into offset 0 regardless of where `self` is.
399
- let mut new = Self { data : MaybeUninit :: uninit_array ( ) , alive : 0 .. 0 } ;
390
+ let mut new = Self { data : MaybeUninit :: uninit_array ( ) , alive : IndexRange :: zero_to ( 0 ) } ;
400
391
401
392
// Clone all alive elements.
402
393
for ( src, dst) in iter:: zip ( self . as_slice ( ) , & mut new. data ) {
403
394
// Write a clone into the new array, then update its alive range.
404
395
// If cloning panics, we'll correctly drop the previous items.
405
396
dst. write ( src. clone ( ) ) ;
406
- new. alive . end += 1 ;
397
+ // This addition cannot overflow as we're iterating a slice
398
+ new. alive = IndexRange :: zero_to ( new. alive . end ( ) + 1 ) ;
407
399
}
408
400
409
401
new
0 commit comments