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_impls", since = "1.40.0")]
228impl<T, const N: usize> Iterator for IntoIter<T, N> {
229    type Item = T;
230
231    #[inline]
232    fn next(&mut self) -> Option<Self::Item> {
233        self.unsize_mut().next()
234    }
235
236    #[inline]
237    fn size_hint(&self) -> (usize, Option<usize>) {
238        self.unsize().size_hint()
239    }
240
241    #[inline]
242    fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
243    where
244        Fold: FnMut(Acc, Self::Item) -> Acc,
245    {
246        self.unsize_mut().fold(init, fold)
247    }
248
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]
260    fn count(self) -> usize {
261        self.len()
262    }
263
264    #[inline]
265    fn last(mut self) -> Option<Self::Item> {
266        self.next_back()
267    }
268
269    #[inline]
270    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
271        self.unsize_mut().advance_by(n)
272    }
273
274    #[inline]
275    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item {
276        // SAFETY: The caller must provide an idx that is in bound of the remainder.
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) }
281    }
282}
283
284#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
285impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
286    #[inline]
287    fn next_back(&mut self) -> Option<Self::Item> {
288        self.unsize_mut().next_back()
289    }
290
291    #[inline]
292    fn rfold<Acc, Fold>(mut self, init: Acc, rfold: Fold) -> Acc
293    where
294        Fold: FnMut(Acc, Self::Item) -> Acc,
295    {
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)
307    }
308
309    #[inline]
310    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
311        self.unsize_mut().advance_back_by(n)
312    }
313}
314
315#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
316impl<T, const N: usize> Drop for IntoIter<T, N> {
317    #[inline]
318    fn drop(&mut self) {
319        // `inner` now handles this, but it'd technically be a breaking change
320        // to remove this `impl`, even though it's useless.
321    }
322}
323
324#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
325impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
326    #[inline]
327    fn len(&self) -> usize {
328        self.inner.len()
329    }
330    #[inline]
331    fn is_empty(&self) -> bool {
332        self.inner.len() == 0
333    }
334}
335
336#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
337impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
338
339// The iterator indeed reports the correct length. The number of "alive"
340// elements (that will still be yielded) is the length of the range `alive`.
341// This range is decremented in length in either `next` or `next_back`. It is
342// always decremented by 1 in those methods, but only if `Some(_)` is returned.
343#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
344unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}
345
346#[doc(hidden)]
347#[unstable(issue = "none", feature = "std_internals")]
348#[rustc_unsafe_specialization_marker]
349pub trait NonDrop {}
350
351// T: Copy as approximation for !Drop since get_unchecked does not advance self.alive
352// and thus we can't implement drop-handling
353#[unstable(issue = "none", feature = "std_internals")]
354impl<T: Copy> NonDrop for T {}
355
356#[doc(hidden)]
357#[unstable(issue = "none", feature = "std_internals")]
358unsafe impl<T, const N: usize> TrustedRandomAccessNoCoerce for IntoIter<T, N>
359where
360    T: NonDrop,
361{
362    const MAY_HAVE_SIDE_EFFECT: bool = false;
363}
364
365#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
366impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
367    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
368        self.unsize().fmt(f)
369    }
370}
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