]> git.lizzy.rs Git - rust.git/blob - library/core/src/array/iter.rs
Auto merge of #88098 - Amanieu:oom_panic, r=nagisa
[rust.git] / library / core / src / array / iter.rs
1 //! Defines the `IntoIter` owned iterator for arrays.
2
3 use crate::{
4     cmp, fmt,
5     iter::{self, ExactSizeIterator, FusedIterator, TrustedLen},
6     mem::{self, MaybeUninit},
7     ops::Range,
8     ptr,
9 };
10
11 /// A by-value [array] iterator.
12 #[stable(feature = "array_value_iter", since = "1.51.0")]
13 #[rustc_insignificant_dtor]
14 pub 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],
28
29     /// The elements in `data` that have not been yielded yet.
30     ///
31     /// Invariants:
32     /// - `alive.start <= alive.end`
33     /// - `alive.end <= N`
34     alive: Range<usize>,
35 }
36
37 // Note: the `#[rustc_skip_array_during_method_dispatch]` on `trait IntoIterator`
38 // hides this implementation from explicit `.into_iter()` calls on editions < 2021,
39 // so those calls will still resolve to the slice implementation, by reference.
40 #[stable(feature = "array_into_iter_impl", since = "1.53.0")]
41 impl<T, const N: usize> IntoIterator for [T; N] {
42     type Item = T;
43     type IntoIter = IntoIter<T, N>;
44
45     /// Creates a consuming iterator, that is, one that moves each value out of
46     /// the array (from start to end). The array cannot be used after calling
47     /// this unless `T` implements `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     fn into_iter(self) -> Self::IntoIter {
54         // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
55         // promise:
56         //
57         // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
58         // > as `T`.
59         //
60         // The docs even show a transmute from an array of `MaybeUninit<T>` to
61         // an array of `T`.
62         //
63         // With that, this initialization satisfies the invariants.
64
65         // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
66         // works with const generics:
67         //     `mem::transmute::<[T; N], [MaybeUninit<T>; N]>(array)`
68         //
69         // Until then, we can use `mem::transmute_copy` to create a bitwise copy
70         // as a different type, then forget `array` so that it is not dropped.
71         unsafe {
72             let iter = IntoIter { data: mem::transmute_copy(&self), alive: 0..N };
73             mem::forget(self);
74             iter
75         }
76     }
77 }
78
79 impl<T, const N: usize> IntoIter<T, N> {
80     /// Creates a new iterator over the given `array`.
81     #[stable(feature = "array_value_iter", since = "1.51.0")]
82     #[rustc_deprecated(since = "1.59.0", reason = "use `IntoIterator::into_iter` instead")]
83     pub fn new(array: [T; N]) -> Self {
84         IntoIterator::into_iter(array)
85     }
86
87     /// Creates an iterator over the elements in a partially-initialized buffer.
88     ///
89     /// If you have a fully-initialized array, then use [`IntoIterator`].
90     /// But this is useful for returning partial results from unsafe code.
91     ///
92     /// # Safety
93     ///
94     /// - The `buffer[initialized]` elements must all be initialized.
95     /// - The range must be canonical, with `initialized.start <= initialized.end`.
96     /// - The range must be in-bounds for the buffer, with `initialized.end <= N`.
97     ///   (Like how indexing `[0][100..100]` fails despite the range being empty.)
98     ///
99     /// It's sound to have more elements initialized than mentioned, though that
100     /// will most likely result in them being leaked.
101     ///
102     /// # Examples
103     ///
104     /// ```
105     /// #![feature(array_into_iter_constructors)]
106     ///
107     /// #![feature(maybe_uninit_array_assume_init)]
108     /// #![feature(maybe_uninit_uninit_array)]
109     /// use std::array::IntoIter;
110     /// use std::mem::MaybeUninit;
111     ///
112     /// # // Hi!  Thanks for reading the code.  This is restricted to `Copy` because
113     /// # // otherwise it could leak.  A fully-general version this would need a drop
114     /// # // guard to handle panics from the iterator, but this works for an example.
115     /// fn next_chunk<T: Copy, const N: usize>(
116     ///     it: &mut impl Iterator<Item = T>,
117     /// ) -> Result<[T; N], IntoIter<T, N>> {
118     ///     let mut buffer = MaybeUninit::uninit_array();
119     ///     let mut i = 0;
120     ///     while i < N {
121     ///         match it.next() {
122     ///             Some(x) => {
123     ///                 buffer[i].write(x);
124     ///                 i += 1;
125     ///             }
126     ///             None => {
127     ///                 // SAFETY: We've initialized the first `i` items
128     ///                 unsafe {
129     ///                     return Err(IntoIter::new_unchecked(buffer, 0..i));
130     ///                 }
131     ///             }
132     ///         }
133     ///     }
134     ///
135     ///     // SAFETY: We've initialized all N items
136     ///     unsafe { Ok(MaybeUninit::array_assume_init(buffer)) }
137     /// }
138     ///
139     /// let r: [_; 4] = next_chunk(&mut (10..16)).unwrap();
140     /// assert_eq!(r, [10, 11, 12, 13]);
141     /// let r: IntoIter<_, 40> = next_chunk(&mut (10..16)).unwrap_err();
142     /// assert_eq!(r.collect::<Vec<_>>(), vec![10, 11, 12, 13, 14, 15]);
143     /// ```
144     #[unstable(feature = "array_into_iter_constructors", issue = "91583")]
145     #[rustc_const_unstable(feature = "const_array_into_iter_constructors", issue = "91583")]
146     pub const unsafe fn new_unchecked(
147         buffer: [MaybeUninit<T>; N],
148         initialized: Range<usize>,
149     ) -> Self {
150         Self { data: buffer, alive: initialized }
151     }
152
153     /// Creates an iterator over `T` which returns no elements.
154     ///
155     /// If you just need an empty iterator, then use
156     /// [`iter::empty()`](crate::iter::empty) instead.
157     /// And if you need an empty array, use `[]`.
158     ///
159     /// But this is useful when you need an `array::IntoIter<T, N>` *specifically*.
160     ///
161     /// # Examples
162     ///
163     /// ```
164     /// #![feature(array_into_iter_constructors)]
165     /// use std::array::IntoIter;
166     ///
167     /// let empty = IntoIter::<i32, 3>::empty();
168     /// assert_eq!(empty.len(), 0);
169     /// assert_eq!(empty.as_slice(), &[]);
170     ///
171     /// let empty = IntoIter::<std::convert::Infallible, 200>::empty();
172     /// assert_eq!(empty.len(), 0);
173     /// ```
174     ///
175     /// `[1, 2].into_iter()` and `[].into_iter()` have different types
176     /// ```should_fail,edition2021
177     /// #![feature(array_into_iter_constructors)]
178     /// use std::array::IntoIter;
179     ///
180     /// pub fn get_bytes(b: bool) -> IntoIter<i8, 4> {
181     ///     if b {
182     ///         [1, 2, 3, 4].into_iter()
183     ///     } else {
184     ///         [].into_iter() // error[E0308]: mismatched types
185     ///     }
186     /// }
187     /// ```
188     ///
189     /// But using this method you can get an empty iterator of appropriate size:
190     /// ```edition2021
191     /// #![feature(array_into_iter_constructors)]
192     /// use std::array::IntoIter;
193     ///
194     /// pub fn get_bytes(b: bool) -> IntoIter<i8, 4> {
195     ///     if b {
196     ///         [1, 2, 3, 4].into_iter()
197     ///     } else {
198     ///         IntoIter::empty()
199     ///     }
200     /// }
201     ///
202     /// assert_eq!(get_bytes(true).collect::<Vec<_>>(), vec![1, 2, 3, 4]);
203     /// assert_eq!(get_bytes(false).collect::<Vec<_>>(), vec![]);
204     /// ```
205     #[unstable(feature = "array_into_iter_constructors", issue = "91583")]
206     #[rustc_const_unstable(feature = "const_array_into_iter_constructors", issue = "91583")]
207     pub const fn empty() -> Self {
208         let buffer = MaybeUninit::uninit_array();
209         let initialized = 0..0;
210
211         // SAFETY: We're telling it that none of the elements are initialized,
212         // which is trivially true.  And ∀N: usize, 0 <= N.
213         unsafe { Self::new_unchecked(buffer, initialized) }
214     }
215
216     /// Returns an immutable slice of all elements that have not been yielded
217     /// yet.
218     #[stable(feature = "array_value_iter", since = "1.51.0")]
219     pub fn as_slice(&self) -> &[T] {
220         // SAFETY: We know that all elements within `alive` are properly initialized.
221         unsafe {
222             let slice = self.data.get_unchecked(self.alive.clone());
223             MaybeUninit::slice_assume_init_ref(slice)
224         }
225     }
226
227     /// Returns a mutable slice of all elements that have not been yielded yet.
228     #[stable(feature = "array_value_iter", since = "1.51.0")]
229     pub fn as_mut_slice(&mut self) -> &mut [T] {
230         // SAFETY: We know that all elements within `alive` are properly initialized.
231         unsafe {
232             let slice = self.data.get_unchecked_mut(self.alive.clone());
233             MaybeUninit::slice_assume_init_mut(slice)
234         }
235     }
236 }
237
238 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
239 impl<T, const N: usize> Iterator for IntoIter<T, N> {
240     type Item = T;
241     fn next(&mut self) -> Option<Self::Item> {
242         // Get the next index from the front.
243         //
244         // Increasing `alive.start` by 1 maintains the invariant regarding
245         // `alive`. However, due to this change, for a short time, the alive
246         // zone is not `data[alive]` anymore, but `data[idx..alive.end]`.
247         self.alive.next().map(|idx| {
248             // Read the element from the array.
249             // SAFETY: `idx` is an index into the former "alive" region of the
250             // array. Reading this element means that `data[idx]` is regarded as
251             // dead now (i.e. do not touch). As `idx` was the start of the
252             // alive-zone, the alive zone is now `data[alive]` again, restoring
253             // all invariants.
254             unsafe { self.data.get_unchecked(idx).assume_init_read() }
255         })
256     }
257
258     fn size_hint(&self) -> (usize, Option<usize>) {
259         let len = self.len();
260         (len, Some(len))
261     }
262
263     #[inline]
264     fn fold<Acc, Fold>(mut self, init: Acc, mut fold: Fold) -> Acc
265     where
266         Fold: FnMut(Acc, Self::Item) -> Acc,
267     {
268         let data = &mut self.data;
269         self.alive.by_ref().fold(init, |acc, idx| {
270             // SAFETY: idx is obtained by folding over the `alive` range, which implies the
271             // value is currently considered alive but as the range is being consumed each value
272             // we read here will only be read once and then considered dead.
273             fold(acc, unsafe { data.get_unchecked(idx).assume_init_read() })
274         })
275     }
276
277     fn count(self) -> usize {
278         self.len()
279     }
280
281     fn last(mut self) -> Option<Self::Item> {
282         self.next_back()
283     }
284
285     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);
292
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;
296
297         // SAFETY: These elements are currently initialized, so it's fine to drop them.
298         unsafe {
299             let slice = self.data.get_unchecked_mut(range_to_drop);
300             ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
301         }
302
303         if n > len { Err(len) } else { Ok(()) }
304     }
305 }
306
307 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
308 impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
309     fn next_back(&mut self) -> Option<Self::Item> {
310         // Get the next index from the back.
311         //
312         // Decreasing `alive.end` by 1 maintains the invariant regarding
313         // `alive`. However, due to this change, for a short time, the alive
314         // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`.
315         self.alive.next_back().map(|idx| {
316             // Read the element from the array.
317             // SAFETY: `idx` is an index into the former "alive" region of the
318             // array. Reading this element means that `data[idx]` is regarded as
319             // dead now (i.e. do not touch). As `idx` was the end of the
320             // alive-zone, the alive zone is now `data[alive]` again, restoring
321             // all invariants.
322             unsafe { self.data.get_unchecked(idx).assume_init_read() }
323         })
324     }
325
326     fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
327         let len = self.len();
328
329         // The number of elements to drop.  Always in-bounds by construction.
330         let delta = cmp::min(n, len);
331
332         let range_to_drop = (self.alive.end - delta)..self.alive.end;
333
334         // Moving the end marks them as conceptually "dropped", so if anything
335         // goes bad then our drop impl won't double-free them.
336         self.alive.end -= delta;
337
338         // SAFETY: These elements are currently initialized, so it's fine to drop them.
339         unsafe {
340             let slice = self.data.get_unchecked_mut(range_to_drop);
341             ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
342         }
343
344         if n > len { Err(len) } else { Ok(()) }
345     }
346 }
347
348 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
349 impl<T, const N: usize> Drop for IntoIter<T, N> {
350     fn drop(&mut self) {
351         // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
352         // of elements that have not been moved out yet and that remain
353         // to be dropped.
354         unsafe { ptr::drop_in_place(self.as_mut_slice()) }
355     }
356 }
357
358 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
359 impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
360     fn len(&self) -> usize {
361         // Will never underflow due to the invariant `alive.start <=
362         // alive.end`.
363         self.alive.end - self.alive.start
364     }
365     fn is_empty(&self) -> bool {
366         self.alive.is_empty()
367     }
368 }
369
370 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
371 impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
372
373 // The iterator indeed reports the correct length. The number of "alive"
374 // elements (that will still be yielded) is the length of the range `alive`.
375 // This range is decremented in length in either `next` or `next_back`. It is
376 // always decremented by 1 in those methods, but only if `Some(_)` is returned.
377 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
378 unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}
379
380 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
381 impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
382     fn clone(&self) -> Self {
383         // Note, we don't really need to match the exact same alive range, so
384         // we can just clone into offset 0 regardless of where `self` is.
385         let mut new = Self { data: MaybeUninit::uninit_array(), alive: 0..0 };
386
387         // Clone all alive elements.
388         for (src, dst) in iter::zip(self.as_slice(), &mut new.data) {
389             // Write a clone into the new array, then update its alive range.
390             // If cloning panics, we'll correctly drop the previous items.
391             dst.write(src.clone());
392             new.alive.end += 1;
393         }
394
395         new
396     }
397 }
398
399 #[stable(feature = "array_value_iter_impls", since = "1.40.0")]
400 impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
401     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402         // Only print the elements that were not yielded yet: we cannot
403         // access the yielded elements anymore.
404         f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
405     }
406 }