core/array/
iter.rs

1//! Defines the `IntoIter` owned iterator for arrays.
2
3use crate::intrinsics::transmute_unchecked;
4use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce};
5use crate::mem::MaybeUninit;
6use crate::num::NonZero;
7use crate::ops::{IndexRange, Range, Try};
8use crate::{fmt, ptr};
9
10mod iter_inner;
11
12type InnerSized<T, const N: usize> = iter_inner::PolymorphicIter<[MaybeUninit<T>; N]>;
13type InnerUnsized<T> = iter_inner::PolymorphicIter<[MaybeUninit<T>]>;
14
15/// A by-value [array] iterator.
16#[stable(feature = "array_value_iter", since = "1.51.0")]
17#[rustc_insignificant_dtor]
18#[rustc_diagnostic_item = "ArrayIntoIter"]
19#[derive(Clone)]
20pub struct IntoIter<T, const N: usize> {
21    inner: InnerSized<T, N>,
22}
23
24impl<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    }
33}
34
35// Note: the `#[rustc_skip_during_method_dispatch(array)]` on `trait IntoIterator`
36// hides this implementation from explicit `.into_iter()` calls on editions < 2021,
37// so those calls will still resolve to the slice implementation, by reference.
38#[stable(feature = "array_into_iter_impl", since = "1.53.0")]
39impl<T, const N: usize> IntoIterator for [T; N] {
40    type Item = T;
41    type IntoIter = IntoIter<T, N>;
42
43    /// Creates a consuming iterator, that is, one that moves each value out of
44    /// the array (from start to end).
45    ///
46    /// The array cannot be used after calling this unless `T` implements
47    /// `Copy`, so the whole array is copied.
48    ///
49    /// Arrays have special behavior when calling `.into_iter()` prior to the
50    /// 2021 edition -- see the [array] Editions section for more information.
51    ///
52    /// [array]: prim@array
53    #[inline]
54    fn into_iter(self) -> Self::IntoIter {
55        // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
56        // promise:
57        //
58        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
59        // > as `T`.
60        //
61        // The docs even show a transmute from an array of `MaybeUninit<T>` to
62        // an array of `T`.
63        //
64        // With that, this initialization satisfies the invariants.
65        //
66        // FIXME: If normal `transmute` ever gets smart enough to allow this
67        // directly, use it instead of `transmute_unchecked`.
68        let data: [MaybeUninit<T>; N] = unsafe { transmute_unchecked(self) };
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 }
73    }
74}
75
76impl<T, const N: usize> IntoIter<T, N> {
77    /// Creates a new iterator over the given `array`.
78    #[stable(feature = "array_value_iter", since = "1.51.0")]
79    #[deprecated(since = "1.59.0", note = "use `IntoIterator::into_iter` instead")]
80    pub fn new(array: [T; N]) -> Self {
81        IntoIterator::into_iter(array)
82    }
83
84    /// Creates an iterator over the elements in a partially-initialized buffer.
85    ///
86    /// If you have a fully-initialized array, then use [`IntoIterator`].
87    /// But this is useful for returning partial results from unsafe code.
88    ///
89    /// # Safety
90    ///
91    /// - The `buffer[initialized]` elements must all be initialized.
92    /// - The range must be canonical, with `initialized.start <= initialized.end`.
93    /// - The range must be in-bounds for the buffer, with `initialized.end <= N`.
94    ///   (Like how indexing `[0][100..100]` fails despite the range being empty.)
95    ///
96    /// It's sound to have more elements initialized than mentioned, though that
97    /// will most likely result in them being leaked.
98    ///
99    /// # Examples
100    ///
101    /// ```
102    /// #![feature(array_into_iter_constructors)]
103    /// #![feature(maybe_uninit_uninit_array_transpose)]
104    /// use std::array::IntoIter;
105    /// use std::mem::MaybeUninit;
106    ///
107    /// # // Hi!  Thanks for reading the code. This is restricted to `Copy` because
108    /// # // otherwise it could leak. A fully-general version this would need a drop
109    /// # // guard to handle panics from the iterator, but this works for an example.
110    /// fn next_chunk<T: Copy, const N: usize>(
111    ///     it: &mut impl Iterator<Item = T>,
112    /// ) -> Result<[T; N], IntoIter<T, N>> {
113    ///     let mut buffer = [const { MaybeUninit::uninit() }; N];
114    ///     let mut i = 0;
115    ///     while i < N {
116    ///         match it.next() {
117    ///             Some(x) => {
118    ///                 buffer[i].write(x);
119    ///                 i += 1;
120    ///             }
121    ///             None => {
122    ///                 // SAFETY: We've initialized the first `i` items
123    ///                 unsafe {
124    ///                     return Err(IntoIter::new_unchecked(buffer, 0..i));
125    ///                 }
126    ///             }
127    ///         }
128    ///     }
129    ///
130    ///     // SAFETY: We've initialized all N items
131    ///     unsafe { Ok(buffer.transpose().assume_init()) }
132    /// }
133    ///
134    /// let r: [_; 4] = next_chunk(&mut (10..16)).unwrap();
135    /// assert_eq!(r, [10, 11, 12, 13]);
136    /// let r: IntoIter<_, 40> = next_chunk(&mut (10..16)).unwrap_err();
137    /// assert_eq!(r.collect::<Vec<_>>(), vec![10, 11, 12, 13, 14, 15]);
138    /// ```
139    #[unstable(feature = "array_into_iter_constructors", issue = "91583")]
140    #[inline]
141    pub const unsafe fn new_unchecked(
142        buffer: [MaybeUninit<T>; N],
143        initialized: Range<usize>,
144    ) -> Self {
145        // SAFETY: one of our safety conditions is that the range is canonical.
146        let alive = unsafe { IndexRange::new_unchecked(initialized.start, initialized.end) };
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 }
150    }
151
152    /// Creates an iterator over `T` which returns no elements.
153    ///
154    /// If you just need an empty iterator, then use
155    /// [`iter::empty()`](crate::iter::empty) instead.
156    /// And if you need an empty array, use `[]`.
157    ///
158    /// But this is useful when you need an `array::IntoIter<T, N>` *specifically*.
159    ///
160    /// # Examples
161    ///
162    /// ```
163    /// #![feature(array_into_iter_constructors)]
164    /// use std::array::IntoIter;
165    ///
166    /// let empty = IntoIter::<i32, 3>::empty();
167    /// assert_eq!(empty.len(), 0);
168    /// assert_eq!(empty.as_slice(), &[]);
169    ///
170    /// let empty = IntoIter::<std::convert::Infallible, 200>::empty();
171    /// assert_eq!(empty.len(), 0);
172    /// ```
173    ///
174    /// `[1, 2].into_iter()` and `[].into_iter()` have different types
175    /// ```should_fail,edition2021
176    /// #![feature(array_into_iter_constructors)]
177    /// use std::array::IntoIter;
178    ///
179    /// pub fn get_bytes(b: bool) -> IntoIter<i8, 4> {
180    ///     if b {
181    ///         [1, 2, 3, 4].into_iter()
182    ///     } else {
183    ///         [].into_iter() // error[E0308]: mismatched types
184    ///     }
185    /// }
186    /// ```
187    ///
188    /// But using this method you can get an empty iterator of appropriate size:
189    /// ```edition2021
190    /// #![feature(array_into_iter_constructors)]
191    /// use std::array::IntoIter;
192    ///
193    /// pub fn get_bytes(b: bool) -> IntoIter<i8, 4> {
194    ///     if b {
195    ///         [1, 2, 3, 4].into_iter()
196    ///     } else {
197    ///         IntoIter::empty()
198    ///     }
199    /// }
200    ///
201    /// assert_eq!(get_bytes(true).collect::<Vec<_>>(), vec![1, 2, 3, 4]);
202    /// assert_eq!(get_bytes(false).collect::<Vec<_>>(), vec![]);
203    /// ```
204    #[unstable(feature = "array_into_iter_constructors", issue = "91583")]
205    #[inline]
206    pub const fn empty() -> Self {
207        let inner = InnerSized::empty();
208        IntoIter { inner }
209    }
210
211    /// Returns an immutable slice of all elements that have not been yielded
212    /// yet.
213    #[stable(feature = "array_value_iter", since = "1.51.0")]
214    #[inline]
215    pub fn as_slice(&self) -> &[T] {
216        self.unsize().as_slice()
217    }
218
219    /// Returns a mutable slice of all elements that have not been yielded yet.
220    #[stable(feature = "array_value_iter", since = "1.51.0")]
221    #[inline]
222    pub fn as_mut_slice(&mut self) -> &mut [T] {
223        self.unsize_mut().as_mut_slice()
224    }
225}
226
227#[stable(feature = "array_value_iter_default", since = "1.89.0")]
228impl<T, const N: usize> Default for IntoIter<T, N> {
229    fn default() -> Self {
230        IntoIter::empty()
231    }
232}
233
234#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
235impl<T, const N: usize> Iterator for IntoIter<T, N> {
236    type Item = T;
237
238    #[inline]
239    fn next(&mut self) -> Option<Self::Item> {
240        self.unsize_mut().next()
241    }
242
243    #[inline]
244    fn size_hint(&self) -> (usize, Option<usize>) {
245        self.unsize().size_hint()
246    }
247
248    #[inline]
249    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
250    where
251        Fold: FnMut(Acc, Self::Item) -> Acc,
252    {
253        self.unsize_mut().fold(init, fold)
254    }
255
256    #[inline]
257    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
258    where
259        Self: Sized,
260        F: FnMut(B, Self::Item) -> R,
261        R: Try<Output = B>,
262    {
263        self.unsize_mut().try_fold(init, f)
264    }
265
266    #[inline]
267    fn count(self) -> usize {
268        self.len()
269    }
270
271    #[inline]
272    fn last(mut self) -> Option<Self::Item> {
273        self.next_back()
274    }
275
276    #[inline]
277    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
278        self.unsize_mut().advance_by(n)
279    }
280
281    #[inline]
282    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
283        // SAFETY: The caller must provide an idx that is in bound of the remainder.
284        let elem_ref = unsafe { self.as_mut_slice().get_unchecked_mut(idx) };
285        // SAFETY: We only implement `TrustedRandomAccessNoCoerce` for types
286        // which are actually `Copy`, so cannot have multiple-drop issues.
287        unsafe { ptr::read(elem_ref) }
288    }
289}
290
291#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
292impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
293    #[inline]
294    fn next_back(&mut self) -> Option<Self::Item> {
295        self.unsize_mut().next_back()
296    }
297
298    #[inline]
299    fn rfold<Acc, Fold>(mut self, init: Acc, rfold: Fold) -> Acc
300    where
301        Fold: FnMut(Acc, Self::Item) -> Acc,
302    {
303        self.unsize_mut().rfold(init, rfold)
304    }
305
306    #[inline]
307    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
308    where
309        Self: Sized,
310        F: FnMut(B, Self::Item) -> R,
311        R: Try<Output = B>,
312    {
313        self.unsize_mut().try_rfold(init, f)
314    }
315
316    #[inline]
317    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
318        self.unsize_mut().advance_back_by(n)
319    }
320}
321
322#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
323impl<T, const N: usize> Drop for IntoIter<T, N> {
324    #[inline]
325    fn drop(&mut self) {
326        // `inner` now handles this, but it'd technically be a breaking change
327        // to remove this `impl`, even though it's useless.
328    }
329}
330
331#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
332impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
333    #[inline]
334    fn len(&self) -> usize {
335        self.inner.len()
336    }
337    #[inline]
338    fn is_empty(&self) -> bool {
339        self.inner.len() == 0
340    }
341}
342
343#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
344impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
345
346// The iterator indeed reports the correct length. The number of "alive"
347// elements (that will still be yielded) is the length of the range `alive`.
348// This range is decremented in length in either `next` or `next_back`. It is
349// always decremented by 1 in those methods, but only if `Some(_)` is returned.
350#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
351unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}
352
353#[doc(hidden)]
354#[unstable(issue = "none", feature = "std_internals")]
355#[rustc_unsafe_specialization_marker]
356pub trait NonDrop {}
357
358// T: Copy as approximation for !Drop since get_unchecked does not advance self.alive
359// and thus we can't implement drop-handling
360#[unstable(issue = "none", feature = "std_internals")]
361impl<T: Copy> NonDrop for T {}
362
363#[doc(hidden)]
364#[unstable(issue = "none", feature = "std_internals")]
365unsafe impl<T, const N: usize> TrustedRandomAccessNoCoerce for IntoIter<T, N>
366where
367    T: NonDrop,
368{
369    const MAY_HAVE_SIDE_EFFECT: bool = false;
370}
371
372#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
373impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
374    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
375        self.unsize().fmt(f)
376    }
377}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy