@@ -3,7 +3,7 @@ use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedF
3
3
use crate::num::NonZero;
4
4
use crate::ops::Try;
5
5
use core::array;
6
- use core::mem::{ManuallyDrop, MaybeUninit} ;
6
+ use core::mem::MaybeUninit;
7
7
use core::ops::ControlFlow;
8
8
9
9
/// An iterator that filters the elements of `iter` with `predicate`.
@@ -27,6 +27,41 @@ impl<I, P> Filter<I, P> {
27
27
}
28
28
}
29
29
30
+ impl<I, P> Filter<I, P>
31
+ where
32
+ I: Iterator,
33
+ P: FnMut(&I::Item) -> bool,
34
+ {
35
+ #[inline]
36
+ fn next_chunk_dropless<const N: usize>(
37
+ &mut self,
38
+ ) -> Result<[I::Item; N], array::IntoIter<I::Item, N>> {
39
+ let mut array: [MaybeUninit<I::Item>; N] = [const { MaybeUninit::uninit() }; N];
40
+ let mut initialized = 0;
41
+
42
+ let result = self.iter.try_for_each(|element| {
43
+ let idx = initialized;
44
+ initialized = idx + (self.predicate)(&element) as usize;
45
+
46
+ // SAFETY: Loop conditions ensure the index is in bounds.
47
+ unsafe { array.get_unchecked_mut(idx) }.write(element);
48
+
49
+ if initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
50
+ });
51
+
52
+ match result {
53
+ ControlFlow::Break(()) => {
54
+ // SAFETY: The loop above is only explicitly broken when the array has been fully initialized
55
+ Ok(unsafe { MaybeUninit::array_assume_init(array) })
56
+ }
57
+ ControlFlow::Continue(()) => {
58
+ // SAFETY: The range is in bounds since the loop breaks when reaching N elements.
59
+ Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) })
60
+ }
61
+ }
62
+ }
63
+ }
64
+
30
65
#[stable(feature = "core_impl_debug", since = "1.9.0")]
31
66
impl<I: fmt::Debug, P> fmt::Debug for Filter<I, P> {
32
67
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -64,52 +99,15 @@ where
64
99
fn next_chunk<const N: usize>(
65
100
&mut self,
66
101
) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
67
- let mut array: [MaybeUninit<Self::Item>; N] = [const { MaybeUninit::uninit() }; N];
68
-
69
- struct Guard<'a, T> {
70
- array: &'a mut [MaybeUninit<T>],
71
- initialized: usize,
72
- }
73
-
74
- impl<T> Drop for Guard<'_, T> {
75
- #[inline]
76
- fn drop(&mut self) {
77
- if const { crate::mem::needs_drop::<T>() } {
78
- // SAFETY: self.initialized is always <= N, which also is the length of the array.
79
- unsafe {
80
- core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
81
- self.array.get_unchecked_mut(..self.initialized),
82
- ));
83
- }
84
- }
102
+ let fun = const {
103
+ if crate::mem::needs_drop::<I::Item>() {
104
+ array::iter_next_chunk::<I::Item, N>
105
+ } else {
106
+ Self::next_chunk_dropless::<N>
85
107
}
86
- }
87
-
88
- let mut guard = Guard { array: &mut array, initialized: 0 };
89
-
90
- let result = self.iter.try_for_each(|element| {
91
- let idx = guard.initialized;
92
- guard.initialized = idx + (self.predicate)(&element) as usize;
93
-
94
- // SAFETY: Loop conditions ensure the index is in bounds.
95
- unsafe { guard.array.get_unchecked_mut(idx) }.write(element);
96
-
97
- if guard.initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
98
- });
108
+ };
99
109
100
- let guard = ManuallyDrop::new(guard);
101
-
102
- match result {
103
- ControlFlow::Break(()) => {
104
- // SAFETY: The loop above is only explicitly broken when the array has been fully initialized
105
- Ok(unsafe { MaybeUninit::array_assume_init(array) })
106
- }
107
- ControlFlow::Continue(()) => {
108
- let initialized = guard.initialized;
109
- // SAFETY: The range is in bounds since the loop breaks when reaching N elements.
110
- Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) })
111
- }
112
- }
110
+ fun(self)
113
111
}
114
112
115
113
#[inline]
0 commit comments