@@ -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,42 @@ 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
+ // branchless index update combined with unconditionally copying the value even when
45
+ // it is filtered reduces branching and dependencies in the loop.
46
+ initialized = idx + ( self . predicate ) ( & element) as usize ;
47
+ // SAFETY: Loop conditions ensure the index is in bounds.
48
+ unsafe { array. get_unchecked_mut ( idx) } . write ( element) ;
49
+
50
+ if initialized < N { ControlFlow :: Continue ( ( ) ) } else { ControlFlow :: Break ( ( ) ) }
51
+ } ) ;
52
+
53
+ match result {
54
+ ControlFlow :: Break ( ( ) ) => {
55
+ // SAFETY: The loop above is only explicitly broken when the array has been fully initialized
56
+ Ok ( unsafe { MaybeUninit :: array_assume_init ( array) } )
57
+ }
58
+ ControlFlow :: Continue ( ( ) ) => {
59
+ // SAFETY: The range is in bounds since the loop breaks when reaching N elements.
60
+ Err ( unsafe { array:: IntoIter :: new_unchecked ( array, 0 ..initialized) } )
61
+ }
62
+ }
63
+ }
64
+ }
65
+
30
66
#[ stable( feature = "core_impl_debug" , since = "1.9.0" ) ]
31
67
impl < I : fmt:: Debug , P > fmt:: Debug for Filter < I , P > {
32
68
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
@@ -64,52 +100,16 @@ where
64
100
fn next_chunk < const N : usize > (
65
101
& mut self ,
66
102
) -> 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
- }
103
+ // avoid codegen for the dead branch
104
+ let fun = const {
105
+ if crate :: mem:: needs_drop :: < I :: Item > ( ) {
106
+ array:: iter_next_chunk :: < I :: Item , N >
107
+ } else {
108
+ Self :: next_chunk_dropless :: < N >
85
109
}
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
- } ) ;
110
+ } ;
99
111
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
- }
112
+ fun ( self )
113
113
}
114
114
115
115
#[ inline]
0 commit comments