@@ -3,7 +3,7 @@ use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedF
33use crate :: num:: NonZero ;
44use crate :: ops:: Try ;
55use core:: array;
6- use core:: mem:: { ManuallyDrop , MaybeUninit } ;
6+ use core:: mem:: MaybeUninit ;
77use core:: ops:: ControlFlow ;
88
99/// An iterator that filters the elements of `iter` with `predicate`.
@@ -27,6 +27,41 @@ impl<I, P> Filter<I, P> {
2727 }
2828}
2929
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+
3065#[ stable( feature = "core_impl_debug" , since = "1.9.0" ) ]
3166impl < I : fmt:: Debug , P > fmt:: Debug for Filter < I , P > {
3267 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
@@ -64,52 +99,15 @@ where
6499 fn next_chunk < const N : usize > (
65100 & mut self ,
66101 ) -> 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 >
85107 }
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+ } ;
99109
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 )
113111 }
114112
115113 #[ inline]
0 commit comments