core/array/iter/iter_inner.rs
1//! Defines the `IntoIter` owned iterator for arrays.
2
3use crate::mem::MaybeUninit;
4#[cfg(not(feature = "ferrocene_certified"))]
5use crate::num::NonZero;
6#[cfg(not(feature = "ferrocene_certified"))]
7use crate::ops::{IndexRange, NeverShortCircuit, Try};
8#[cfg(not(feature = "ferrocene_certified"))]
9use crate::{fmt, iter};
10
11// Ferrocene addition: imports for certified subset
12#[cfg(feature = "ferrocene_certified")]
13#[rustfmt::skip]
14use crate::{iter, ops::IndexRange};
15
16#[allow(private_bounds)]
17trait PartialDrop {
18    /// # Safety
19    /// `self[alive]` are all initialized before the call,
20    /// then are never used (without reinitializing them) after it.
21    unsafe fn partial_drop(&mut self, alive: IndexRange);
22}
23impl<T> PartialDrop for [MaybeUninit<T>] {
24    unsafe fn partial_drop(&mut self, alive: IndexRange) {
25        // SAFETY: We know that all elements within `alive` are properly initialized.
26        unsafe { self.get_unchecked_mut(alive).assume_init_drop() }
27    }
28}
29impl<T, const N: usize> PartialDrop for [MaybeUninit<T>; N] {
30    unsafe fn partial_drop(&mut self, alive: IndexRange) {
31        let slice: &mut [MaybeUninit<T>] = self;
32        // SAFETY: Initialized elements in the array are also initialized in the slice.
33        unsafe { slice.partial_drop(alive) }
34    }
35}
36
37/// The internals of a by-value array iterator.
38///
39/// The real `array::IntoIter<T, N>` stores a `PolymorphicIter<[MaybeUninit<T>, N]>`
40/// which it unsizes to `PolymorphicIter<[MaybeUninit<T>]>` to iterate.
41#[allow(private_bounds)]
42pub(super) struct PolymorphicIter<DATA: ?Sized>
43where
44    DATA: PartialDrop,
45{
46    /// The elements in `data` that have not been yielded yet.
47    ///
48    /// Invariants:
49    /// - `alive.end <= N`
50    ///
51    /// (And the `IndexRange` type requires `alive.start <= alive.end`.)
52    alive: IndexRange,
53
54    /// This is the array we are iterating over.
55    ///
56    /// Elements with index `i` where `alive.start <= i < alive.end` have not
57    /// been yielded yet and are valid array entries. Elements with indices `i
58    /// < alive.start` or `i >= alive.end` have been yielded already and must
59    /// not be accessed anymore! Those dead elements might even be in a
60    /// completely uninitialized state!
61    ///
62    /// So the invariants are:
63    /// - `data[alive]` is alive (i.e. contains valid elements)
64    /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
65    ///   elements were already read and must not be touched anymore!)
66    data: DATA,
67}
68
69#[allow(private_bounds)]
70impl<DATA: ?Sized> PolymorphicIter<DATA>
71where
72    DATA: PartialDrop,
73{
74    #[inline]
75    pub(super) const fn len(&self) -> usize {
76        self.alive.len()
77    }
78}
79
80#[allow(private_bounds)]
81impl<DATA: ?Sized> Drop for PolymorphicIter<DATA>
82where
83    DATA: PartialDrop,
84{
85    #[inline]
86    fn drop(&mut self) {
87        // SAFETY: by our type invariant `self.alive` is exactly the initialized
88        // items, and this is drop so nothing can use the items afterwards.
89        unsafe { self.data.partial_drop(self.alive.clone()) }
90    }
91}
92
93impl<T, const N: usize> PolymorphicIter<[MaybeUninit<T>; N]> {
94    #[inline]
95    pub(super) const fn empty() -> Self {
96        Self { alive: IndexRange::zero_to(0), data: [const { MaybeUninit::uninit() }; N] }
97    }
98
99    /// # Safety
100    /// `data[alive]` are all initialized.
101    #[inline]
102    pub(super) const unsafe fn new_unchecked(alive: IndexRange, data: [MaybeUninit<T>; N]) -> Self {
103        Self { alive, data }
104    }
105}
106
107impl<T: Clone, const N: usize> Clone for PolymorphicIter<[MaybeUninit<T>; N]> {
108    #[inline]
109    fn clone(&self) -> Self {
110        // Note, we don't really need to match the exact same alive range, so
111        // we can just clone into offset 0 regardless of where `self` is.
112        let mut new = Self::empty();
113
114        fn clone_into_new<U: Clone>(
115            source: &PolymorphicIter<[MaybeUninit<U>]>,
116            target: &mut PolymorphicIter<[MaybeUninit<U>]>,
117        ) {
118            // Clone all alive elements.
119            for (src, dst) in iter::zip(source.as_slice(), &mut target.data) {
120                // Write a clone into the new array, then update its alive range.
121                // If cloning panics, we'll correctly drop the previous items.
122                dst.write(src.clone());
123                // This addition cannot overflow as we're iterating a slice,
124                // the length of which always fits in usize.
125                target.alive = IndexRange::zero_to(target.alive.end() + 1);
126            }
127        }
128
129        clone_into_new(self, &mut new);
130        new
131    }
132}
133
134impl<T> PolymorphicIter<[MaybeUninit<T>]> {
135    #[inline]
136    pub(super) fn as_slice(&self) -> &[T] {
137        // SAFETY: We know that all elements within `alive` are properly initialized.
138        unsafe {
139            let slice = self.data.get_unchecked(self.alive.clone());
140            slice.assume_init_ref()
141        }
142    }
143
144    #[inline]
145    #[cfg(not(feature = "ferrocene_certified"))]
146    pub(super) fn as_mut_slice(&mut self) -> &mut [T] {
147        // SAFETY: We know that all elements within `alive` are properly initialized.
148        unsafe {
149            let slice = self.data.get_unchecked_mut(self.alive.clone());
150            slice.assume_init_mut()
151        }
152    }
153}
154
155#[cfg(not(feature = "ferrocene_certified"))]
156impl<T: fmt::Debug> fmt::Debug for PolymorphicIter<[MaybeUninit<T>]> {
157    #[inline]
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        // Only print the elements that were not yielded yet: we cannot
160        // access the yielded elements anymore.
161        f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
162    }
163}
164
165/// Iterator-equivalent methods.
166///
167/// We don't implement the actual iterator traits because we want to implement
168/// things like `try_fold` that require `Self: Sized` (which we're not).
169impl<T> PolymorphicIter<[MaybeUninit<T>]> {
170    #[inline]
171    pub(super) fn next(&mut self) -> Option<T> {
172        // Get the next index from the front.
173        //
174        // Increasing `alive.start` by 1 maintains the invariant regarding
175        // `alive`. However, due to this change, for a short time, the alive
176        // zone is not `data[alive]` anymore, but `data[idx..alive.end]`.
177        self.alive.next().map(|idx| {
178            // Read the element from the array.
179            // SAFETY: `idx` is an index into the former "alive" region of the
180            // array. Reading this element means that `data[idx]` is regarded as
181            // dead now (i.e. do not touch). As `idx` was the start of the
182            // alive-zone, the alive zone is now `data[alive]` again, restoring
183            // all invariants.
184            unsafe { self.data.get_unchecked(idx).assume_init_read() }
185        })
186    }
187
188    #[inline]
189    pub(super) fn size_hint(&self) -> (usize, Option<usize>) {
190        let len = self.len();
191        (len, Some(len))
192    }
193
194    #[inline]
195    #[cfg(not(feature = "ferrocene_certified"))]
196    pub(super) fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
197        // This also moves the start, which marks them as conceptually "dropped",
198        // so if anything goes bad then our drop impl won't double-free them.
199        let range_to_drop = self.alive.take_prefix(n);
200        let remaining = n - range_to_drop.len();
201
202        // SAFETY: These elements are currently initialized, so it's fine to drop them.
203        unsafe {
204            let slice = self.data.get_unchecked_mut(range_to_drop);
205            slice.assume_init_drop();
206        }
207
208        NonZero::new(remaining).map_or(Ok(()), Err)
209    }
210
211    #[inline]
212    #[cfg(not(feature = "ferrocene_certified"))]
213    pub(super) fn fold<B>(&mut self, init: B, f: impl FnMut(B, T) -> B) -> B {
214        self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
215    }
216
217    #[inline]
218    #[cfg(not(feature = "ferrocene_certified"))]
219    pub(super) fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
220    where
221        F: FnMut(B, T) -> R,
222        R: Try<Output = B>,
223    {
224        // `alive` is an `IndexRange`, not an arbitrary iterator, so we can
225        // trust that its `try_fold` isn't going to do something weird like
226        // call the fold-er multiple times for the same index.
227        let data = &mut self.data;
228        self.alive.try_fold(init, move |accum, idx| {
229            // SAFETY: `idx` has been removed from the alive range, so we're not
230            // going to drop it (even if `f` panics) and thus its ok to give
231            // out ownership of that item to `f` to handle.
232            let elem = unsafe { data.get_unchecked(idx).assume_init_read() };
233            f(accum, elem)
234        })
235    }
236
237    #[inline]
238    #[cfg(not(feature = "ferrocene_certified"))]
239    pub(super) fn next_back(&mut self) -> Option<T> {
240        // Get the next index from the back.
241        //
242        // Decreasing `alive.end` by 1 maintains the invariant regarding
243        // `alive`. However, due to this change, for a short time, the alive
244        // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`.
245        self.alive.next_back().map(|idx| {
246            // Read the element from the array.
247            // SAFETY: `idx` is an index into the former "alive" region of the
248            // array. Reading this element means that `data[idx]` is regarded as
249            // dead now (i.e. do not touch). As `idx` was the end of the
250            // alive-zone, the alive zone is now `data[alive]` again, restoring
251            // all invariants.
252            unsafe { self.data.get_unchecked(idx).assume_init_read() }
253        })
254    }
255
256    #[inline]
257    #[cfg(not(feature = "ferrocene_certified"))]
258    pub(super) fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
259        // This also moves the end, which marks them as conceptually "dropped",
260        // so if anything goes bad then our drop impl won't double-free them.
261        let range_to_drop = self.alive.take_suffix(n);
262        let remaining = n - range_to_drop.len();
263
264        // SAFETY: These elements are currently initialized, so it's fine to drop them.
265        unsafe {
266            let slice = self.data.get_unchecked_mut(range_to_drop);
267            slice.assume_init_drop();
268        }
269
270        NonZero::new(remaining).map_or(Ok(()), Err)
271    }
272
273    #[inline]
274    #[cfg(not(feature = "ferrocene_certified"))]
275    pub(super) fn rfold<B>(&mut self, init: B, f: impl FnMut(B, T) -> B) -> B {
276        self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0
277    }
278
279    #[inline]
280    #[cfg(not(feature = "ferrocene_certified"))]
281    pub(super) fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
282    where
283        F: FnMut(B, T) -> R,
284        R: Try<Output = B>,
285    {
286        // `alive` is an `IndexRange`, not an arbitrary iterator, so we can
287        // trust that its `try_rfold` isn't going to do something weird like
288        // call the fold-er multiple times for the same index.
289        let data = &mut self.data;
290        self.alive.try_rfold(init, move |accum, idx| {
291            // SAFETY: `idx` has been removed from the alive range, so we're not
292            // going to drop it (even if `f` panics) and thus its ok to give
293            // out ownership of that item to `f` to handle.
294            let elem = unsafe { data.get_unchecked(idx).assume_init_read() };
295            f(accum, elem)
296        })
297    }
298}