11//! Defines the `IntoIter` owned iterator for arrays.
22
33use crate :: intrinsics:: transmute_unchecked;
4- use crate :: iter:: { self , FusedIterator , TrustedLen , TrustedRandomAccessNoCoerce } ;
4+ use crate :: iter:: { FusedIterator , TrustedLen , TrustedRandomAccessNoCoerce } ;
55use crate :: mem:: MaybeUninit ;
66use crate :: num:: NonZero ;
7- use crate :: ops:: { IndexRange , Range } ;
7+ use crate :: ops:: { IndexRange , Range , Try } ;
88use crate :: { fmt, ptr} ;
99
10+ mod iter_inner;
11+
12+ type InnerSized < T , const N : usize > = iter_inner:: PolymorphicIter < [ MaybeUninit < T > ; N ] > ;
13+ type InnerUnsized < T > = iter_inner:: PolymorphicIter < [ MaybeUninit < T > ] > ;
14+
1015/// A by-value [array] iterator.
1116#[ stable( feature = "array_value_iter" , since = "1.51.0" ) ]
1217#[ rustc_insignificant_dtor]
1318#[ rustc_diagnostic_item = "ArrayIntoIter" ]
19+ #[ derive( Clone ) ]
1420pub struct IntoIter < T , const N : usize > {
15- /// This is the array we are iterating over.
16- ///
17- /// Elements with index `i` where `alive.start <= i < alive.end` have not
18- /// been yielded yet and are valid array entries. Elements with indices `i
19- /// < alive.start` or `i >= alive.end` have been yielded already and must
20- /// not be accessed anymore! Those dead elements might even be in a
21- /// completely uninitialized state!
22- ///
23- /// So the invariants are:
24- /// - `data[alive]` is alive (i.e. contains valid elements)
25- /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
26- /// elements were already read and must not be touched anymore!)
27- data : [ MaybeUninit < T > ; N ] ,
21+ inner : InnerSized < T , N > ,
22+ }
2823
29- /// The elements in `data` that have not been yielded yet.
30- ///
31- /// Invariants:
32- /// - `alive.end <= N`
33- ///
34- /// (And the `IndexRange` type requires `alive.start <= alive.end`.)
35- alive : IndexRange ,
24+ impl < T , const N : usize > IntoIter < T , N > {
25+ #[ inline]
26+ fn unsize ( & self ) -> & InnerUnsized < T > {
27+ & self . inner
28+ }
29+ #[ inline]
30+ fn unsize_mut ( & mut self ) -> & mut InnerUnsized < T > {
31+ & mut self . inner
32+ }
3633}
3734
3835// Note: the `#[rustc_skip_during_method_dispatch(array)]` on `trait IntoIterator`
@@ -53,6 +50,7 @@ impl<T, const N: usize> IntoIterator for [T; N] {
5350 /// 2021 edition -- see the [array] Editions section for more information.
5451 ///
5552 /// [array]: prim@array
53+ #[ inline]
5654 fn into_iter ( self ) -> Self :: IntoIter {
5755 // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
5856 // promise:
@@ -68,7 +66,10 @@ impl<T, const N: usize> IntoIterator for [T; N] {
6866 // FIXME: If normal `transmute` ever gets smart enough to allow this
6967 // directly, use it instead of `transmute_unchecked`.
7068 let data: [ MaybeUninit < T > ; N ] = unsafe { transmute_unchecked ( self ) } ;
71- IntoIter { data, alive : IndexRange :: zero_to ( N ) }
69+ // SAFETY: The original array was entirely initialized and the the alive
70+ // range we're passing here represents that fact.
71+ let inner = unsafe { InnerSized :: new_unchecked ( IndexRange :: zero_to ( N ) , data) } ;
72+ IntoIter { inner }
7273 }
7374}
7475
@@ -136,13 +137,16 @@ impl<T, const N: usize> IntoIter<T, N> {
136137 /// assert_eq!(r.collect::<Vec<_>>(), vec![10, 11, 12, 13, 14, 15]);
137138 /// ```
138139 #[ unstable( feature = "array_into_iter_constructors" , issue = "91583" ) ]
140+ #[ inline]
139141 pub const unsafe fn new_unchecked (
140142 buffer : [ MaybeUninit < T > ; N ] ,
141143 initialized : Range < usize > ,
142144 ) -> Self {
143145 // SAFETY: one of our safety conditions is that the range is canonical.
144146 let alive = unsafe { IndexRange :: new_unchecked ( initialized. start , initialized. end ) } ;
145- Self { data : buffer, alive }
147+ // SAFETY: one of our safety condition is that these items are initialized.
148+ let inner = unsafe { InnerSized :: new_unchecked ( alive, buffer) } ;
149+ IntoIter { inner }
146150 }
147151
148152 /// Creates an iterator over `T` which returns no elements.
@@ -198,172 +202,134 @@ impl<T, const N: usize> IntoIter<T, N> {
198202 /// assert_eq!(get_bytes(false).collect::<Vec<_>>(), vec![]);
199203 /// ```
200204 #[ unstable( feature = "array_into_iter_constructors" , issue = "91583" ) ]
205+ #[ inline]
201206 pub const fn empty ( ) -> Self {
202- let buffer = [ const { MaybeUninit :: uninit ( ) } ; N ] ;
203- let initialized = 0 ..0 ;
204-
205- // SAFETY: We're telling it that none of the elements are initialized,
206- // which is trivially true. And ∀N: usize, 0 <= N.
207- unsafe { Self :: new_unchecked ( buffer, initialized) }
207+ let inner = InnerSized :: empty ( ) ;
208+ IntoIter { inner }
208209 }
209210
210211 /// Returns an immutable slice of all elements that have not been yielded
211212 /// yet.
212213 #[ stable( feature = "array_value_iter" , since = "1.51.0" ) ]
214+ #[ inline]
213215 pub fn as_slice ( & self ) -> & [ T ] {
214- // SAFETY: We know that all elements within `alive` are properly initialized.
215- unsafe {
216- let slice = self . data . get_unchecked ( self . alive . clone ( ) ) ;
217- slice. assume_init_ref ( )
218- }
216+ self . unsize ( ) . as_slice ( )
219217 }
220218
221219 /// Returns a mutable slice of all elements that have not been yielded yet.
222220 #[ stable( feature = "array_value_iter" , since = "1.51.0" ) ]
221+ #[ inline]
223222 pub fn as_mut_slice ( & mut self ) -> & mut [ T ] {
224- // SAFETY: We know that all elements within `alive` are properly initialized.
225- unsafe {
226- let slice = self . data . get_unchecked_mut ( self . alive . clone ( ) ) ;
227- slice. assume_init_mut ( )
228- }
223+ self . unsize_mut ( ) . as_mut_slice ( )
229224 }
230225}
231226
232227#[ stable( feature = "array_value_iter_impls" , since = "1.40.0" ) ]
233228impl < T , const N : usize > Iterator for IntoIter < T , N > {
234229 type Item = T ;
230+
231+ #[ inline]
235232 fn next ( & mut self ) -> Option < Self :: Item > {
236- // Get the next index from the front.
237- //
238- // Increasing `alive.start` by 1 maintains the invariant regarding
239- // `alive`. However, due to this change, for a short time, the alive
240- // zone is not `data[alive]` anymore, but `data[idx..alive.end]`.
241- self . alive . next ( ) . map ( |idx| {
242- // Read the element from the array.
243- // SAFETY: `idx` is an index into the former "alive" region of the
244- // array. Reading this element means that `data[idx]` is regarded as
245- // dead now (i.e. do not touch). As `idx` was the start of the
246- // alive-zone, the alive zone is now `data[alive]` again, restoring
247- // all invariants.
248- unsafe { self . data . get_unchecked ( idx) . assume_init_read ( ) }
249- } )
233+ self . unsize_mut ( ) . next ( )
250234 }
251235
236+ #[ inline]
252237 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
253- let len = self . len ( ) ;
254- ( len, Some ( len) )
238+ self . unsize ( ) . size_hint ( )
255239 }
256240
257241 #[ inline]
258- fn fold < Acc , Fold > ( mut self , init : Acc , mut fold : Fold ) -> Acc
242+ fn fold < Acc , Fold > ( mut self , init : Acc , fold : Fold ) -> Acc
259243 where
260244 Fold : FnMut ( Acc , Self :: Item ) -> Acc ,
261245 {
262- let data = & mut self . data ;
263- iter:: ByRefSized ( & mut self . alive ) . fold ( init, |acc, idx| {
264- // SAFETY: idx is obtained by folding over the `alive` range, which implies the
265- // value is currently considered alive but as the range is being consumed each value
266- // we read here will only be read once and then considered dead.
267- fold ( acc, unsafe { data. get_unchecked ( idx) . assume_init_read ( ) } )
268- } )
246+ self . unsize_mut ( ) . fold ( init, fold)
269247 }
270248
249+ #[ inline]
250+ fn try_fold < B , F , R > ( & mut self , init : B , f : F ) -> R
251+ where
252+ Self : Sized ,
253+ F : FnMut ( B , Self :: Item ) -> R ,
254+ R : Try < Output = B > ,
255+ {
256+ self . unsize_mut ( ) . try_fold ( init, f)
257+ }
258+
259+ #[ inline]
271260 fn count ( self ) -> usize {
272261 self . len ( )
273262 }
274263
264+ #[ inline]
275265 fn last ( mut self ) -> Option < Self :: Item > {
276266 self . next_back ( )
277267 }
278268
269+ #[ inline]
279270 fn advance_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
280- // This also moves the start, which marks them as conceptually "dropped",
281- // so if anything goes bad then our drop impl won't double-free them.
282- let range_to_drop = self . alive . take_prefix ( n) ;
283- let remaining = n - range_to_drop. len ( ) ;
284-
285- // SAFETY: These elements are currently initialized, so it's fine to drop them.
286- unsafe {
287- let slice = self . data . get_unchecked_mut ( range_to_drop) ;
288- slice. assume_init_drop ( ) ;
289- }
290-
291- NonZero :: new ( remaining) . map_or ( Ok ( ( ) ) , Err )
271+ self . unsize_mut ( ) . advance_by ( n)
292272 }
293273
294274 #[ inline]
295275 unsafe fn __iterator_get_unchecked ( & mut self , idx : usize ) -> Self :: Item {
296276 // SAFETY: The caller must provide an idx that is in bound of the remainder.
297- unsafe { self . data . as_ptr ( ) . add ( self . alive . start ( ) ) . add ( idx) . cast :: < T > ( ) . read ( ) }
277+ let elem_ref = unsafe { self . as_mut_slice ( ) . get_unchecked_mut ( idx) } ;
278+ // SAFETY: We only implement `TrustedRandomAccessNoCoerce` for types
279+ // which are actually `Copy`, so cannot have multiple-drop issues.
280+ unsafe { ptr:: read ( elem_ref) }
298281 }
299282}
300283
301284#[ stable( feature = "array_value_iter_impls" , since = "1.40.0" ) ]
302285impl < T , const N : usize > DoubleEndedIterator for IntoIter < T , N > {
286+ #[ inline]
303287 fn next_back ( & mut self ) -> Option < Self :: Item > {
304- // Get the next index from the back.
305- //
306- // Decreasing `alive.end` by 1 maintains the invariant regarding
307- // `alive`. However, due to this change, for a short time, the alive
308- // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`.
309- self . alive . next_back ( ) . map ( |idx| {
310- // Read the element from the array.
311- // SAFETY: `idx` is an index into the former "alive" region of the
312- // array. Reading this element means that `data[idx]` is regarded as
313- // dead now (i.e. do not touch). As `idx` was the end of the
314- // alive-zone, the alive zone is now `data[alive]` again, restoring
315- // all invariants.
316- unsafe { self . data . get_unchecked ( idx) . assume_init_read ( ) }
317- } )
288+ self . unsize_mut ( ) . next_back ( )
318289 }
319290
320291 #[ inline]
321- fn rfold < Acc , Fold > ( mut self , init : Acc , mut rfold : Fold ) -> Acc
292+ fn rfold < Acc , Fold > ( mut self , init : Acc , rfold : Fold ) -> Acc
322293 where
323294 Fold : FnMut ( Acc , Self :: Item ) -> Acc ,
324295 {
325- let data = & mut self . data ;
326- iter:: ByRefSized ( & mut self . alive ) . rfold ( init, |acc, idx| {
327- // SAFETY: idx is obtained by folding over the `alive` range, which implies the
328- // value is currently considered alive but as the range is being consumed each value
329- // we read here will only be read once and then considered dead.
330- rfold ( acc, unsafe { data. get_unchecked ( idx) . assume_init_read ( ) } )
331- } )
296+ self . unsize_mut ( ) . rfold ( init, rfold)
297+ }
298+
299+ #[ inline]
300+ fn try_rfold < B , F , R > ( & mut self , init : B , f : F ) -> R
301+ where
302+ Self : Sized ,
303+ F : FnMut ( B , Self :: Item ) -> R ,
304+ R : Try < Output = B > ,
305+ {
306+ self . unsize_mut ( ) . try_rfold ( init, f)
332307 }
333308
309+ #[ inline]
334310 fn advance_back_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
335- // This also moves the end, which marks them as conceptually "dropped",
336- // so if anything goes bad then our drop impl won't double-free them.
337- let range_to_drop = self . alive . take_suffix ( n) ;
338- let remaining = n - range_to_drop. len ( ) ;
339-
340- // SAFETY: These elements are currently initialized, so it's fine to drop them.
341- unsafe {
342- let slice = self . data . get_unchecked_mut ( range_to_drop) ;
343- slice. assume_init_drop ( ) ;
344- }
345-
346- NonZero :: new ( remaining) . map_or ( Ok ( ( ) ) , Err )
311+ self . unsize_mut ( ) . advance_back_by ( n)
347312 }
348313}
349314
350315#[ stable( feature = "array_value_iter_impls" , since = "1.40.0" ) ]
351316impl < T , const N : usize > Drop for IntoIter < T , N > {
317+ #[ inline]
352318 fn drop ( & mut self ) {
353- // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
354- // of elements that have not been moved out yet and that remain
355- // to be dropped.
356- unsafe { ptr:: drop_in_place ( self . as_mut_slice ( ) ) }
319+ // `inner` now handles this, but it'd technically be a breaking change
320+ // to remove this `impl`, even though it's useless.
357321 }
358322}
359323
360324#[ stable( feature = "array_value_iter_impls" , since = "1.40.0" ) ]
361325impl < T , const N : usize > ExactSizeIterator for IntoIter < T , N > {
326+ #[ inline]
362327 fn len ( & self ) -> usize {
363- self . alive . len ( )
328+ self . inner . len ( )
364329 }
330+ #[ inline]
365331 fn is_empty ( & self ) -> bool {
366- self . alive . is_empty ( )
332+ self . inner . len ( ) == 0
367333 }
368334}
369335
@@ -396,32 +362,9 @@ where
396362 const MAY_HAVE_SIDE_EFFECT : bool = false ;
397363}
398364
399- #[ stable( feature = "array_value_iter_impls" , since = "1.40.0" ) ]
400- impl < T : Clone , const N : usize > Clone for IntoIter < T , N > {
401- fn clone ( & self ) -> Self {
402- // Note, we don't really need to match the exact same alive range, so
403- // we can just clone into offset 0 regardless of where `self` is.
404- let mut new =
405- Self { data : [ const { MaybeUninit :: uninit ( ) } ; N ] , alive : IndexRange :: zero_to ( 0 ) } ;
406-
407- // Clone all alive elements.
408- for ( src, dst) in iter:: zip ( self . as_slice ( ) , & mut new. data ) {
409- // Write a clone into the new array, then update its alive range.
410- // If cloning panics, we'll correctly drop the previous items.
411- dst. write ( src. clone ( ) ) ;
412- // This addition cannot overflow as we're iterating a slice
413- new. alive = IndexRange :: zero_to ( new. alive . end ( ) + 1 ) ;
414- }
415-
416- new
417- }
418- }
419-
420365#[ stable( feature = "array_value_iter_impls" , since = "1.40.0" ) ]
421366impl < T : fmt:: Debug , const N : usize > fmt:: Debug for IntoIter < T , N > {
422367 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
423- // Only print the elements that were not yielded yet: we cannot
424- // access the yielded elements anymore.
425- f. debug_tuple ( "IntoIter" ) . field ( & self . as_slice ( ) ) . finish ( )
368+ self . unsize ( ) . fmt ( f)
426369 }
427370}
0 commit comments