@@ -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