@@ -28,6 +28,22 @@ impl<I> Fuse<I> {
2828#[ stable( feature = "fused" , since = "1.26.0" ) ]
2929impl < I > FusedIterator for Fuse < I > where I : Iterator { }
3030
31+ /// Fuse the iterator if the expression is `None`.
32+ macro_rules! fuse {
33+ ( $self: ident . iter . $( $call: tt) +) => {
34+ match $self. iter {
35+ Some ( ref mut iter) => match iter. $( $call) + {
36+ None => {
37+ $self. iter = None ;
38+ None
39+ }
40+ item => item,
41+ } ,
42+ None => None ,
43+ }
44+ } ;
45+ }
46+
3147#[ stable( feature = "rust1" , since = "1.0.0" ) ]
3248impl < I > Iterator for Fuse < I >
3349where
@@ -37,35 +53,36 @@ where
3753
3854 #[ inline]
3955 default fn next ( & mut self ) -> Option < <I as Iterator >:: Item > {
40- let next = self . iter . as_mut ( ) ?. next ( ) ;
41- if next. is_none ( ) {
42- self . iter = None ;
43- }
44- next
56+ fuse ! ( self . iter. next( ) )
4557 }
4658
4759 #[ inline]
4860 default fn nth ( & mut self , n : usize ) -> Option < I :: Item > {
49- let nth = self . iter . as_mut ( ) ?. nth ( n) ;
50- if nth. is_none ( ) {
51- self . iter = None ;
52- }
53- nth
61+ fuse ! ( self . iter. nth( n) )
5462 }
5563
5664 #[ inline]
5765 default fn last ( self ) -> Option < I :: Item > {
58- self . iter ?. last ( )
66+ match self . iter {
67+ Some ( iter) => iter. last ( ) ,
68+ None => None ,
69+ }
5970 }
6071
6172 #[ inline]
6273 default fn count ( self ) -> usize {
63- self . iter . map_or ( 0 , I :: count)
74+ match self . iter {
75+ Some ( iter) => iter. count ( ) ,
76+ None => 0 ,
77+ }
6478 }
6579
6680 #[ inline]
6781 default fn size_hint ( & self ) -> ( usize , Option < usize > ) {
68- self . iter . as_ref ( ) . map_or ( ( 0 , Some ( 0 ) ) , I :: size_hint)
82+ match self . iter {
83+ Some ( ref iter) => iter. size_hint ( ) ,
84+ None => ( 0 , Some ( 0 ) ) ,
85+ }
6986 }
7087
7188 #[ inline]
@@ -98,11 +115,7 @@ where
98115 where
99116 P : FnMut ( & Self :: Item ) -> bool ,
100117 {
101- let found = self . iter . as_mut ( ) ?. find ( predicate) ;
102- if found. is_none ( ) {
103- self . iter = None ;
104- }
105- found
118+ fuse ! ( self . iter. find( predicate) )
106119 }
107120}
108121
@@ -113,20 +126,12 @@ where
113126{
114127 #[ inline]
115128 default fn next_back ( & mut self ) -> Option < <I as Iterator >:: Item > {
116- let next = self . iter . as_mut ( ) ?. next_back ( ) ;
117- if next. is_none ( ) {
118- self . iter = None ;
119- }
120- next
129+ fuse ! ( self . iter. next_back( ) )
121130 }
122131
123132 #[ inline]
124133 default fn nth_back ( & mut self , n : usize ) -> Option < <I as Iterator >:: Item > {
125- let nth = self . iter . as_mut ( ) ?. nth_back ( n) ;
126- if nth. is_none ( ) {
127- self . iter = None ;
128- }
129- nth
134+ fuse ! ( self . iter. nth_back( n) )
130135 }
131136
132137 #[ inline]
@@ -159,11 +164,7 @@ where
159164 where
160165 P : FnMut ( & Self :: Item ) -> bool ,
161166 {
162- let found = self . iter . as_mut ( ) ?. rfind ( predicate) ;
163- if found. is_none ( ) {
164- self . iter = None ;
165- }
166- found
167+ fuse ! ( self . iter. rfind( predicate) )
167168 }
168169}
169170
@@ -173,42 +174,30 @@ where
173174 I : ExactSizeIterator ,
174175{
175176 default fn len ( & self ) -> usize {
176- self . iter . as_ref ( ) . map_or ( 0 , I :: len)
177- }
178-
179- default fn is_empty ( & self ) -> bool {
180- self . iter . as_ref ( ) . map_or ( true , I :: is_empty)
181- }
182- }
183-
184- // NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`
185- impl < I : FusedIterator > Fuse < I > {
186- #[ inline( always) ]
187- fn as_inner ( & self ) -> & I {
188177 match self . iter {
189- Some ( ref iter) => iter,
190- // SAFETY: the specialized iterator never sets `None`
191- None => unsafe { intrinsics:: unreachable ( ) } ,
178+ Some ( ref iter) => iter. len ( ) ,
179+ None => 0 ,
192180 }
193181 }
194182
195- #[ inline( always) ]
196- fn as_inner_mut ( & mut self ) -> & mut I {
183+ default fn is_empty ( & self ) -> bool {
197184 match self . iter {
198- Some ( ref mut iter) => iter,
199- // SAFETY: the specialized iterator never sets `None`
200- None => unsafe { intrinsics:: unreachable ( ) } ,
185+ Some ( ref iter) => iter. is_empty ( ) ,
186+ None => true ,
201187 }
202188 }
189+ }
203190
204- #[ inline( always) ]
205- fn into_inner ( self ) -> I {
206- match self . iter {
207- Some ( iter) => iter,
191+ // NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`.
192+ // Implementing this as a directly-expanded macro helps codegen performance.
193+ macro_rules! unchecked {
194+ ( $self: ident) => {
195+ match $self {
196+ Fuse { iter: Some ( iter) } => iter,
208197 // SAFETY: the specialized iterator never sets `None`
209- None => unsafe { intrinsics:: unreachable ( ) } ,
198+ Fuse { iter : None } => unsafe { intrinsics:: unreachable( ) } ,
210199 }
211- }
200+ } ;
212201}
213202
214203#[ stable( feature = "fused" , since = "1.26.0" ) ]
@@ -218,27 +207,27 @@ where
218207{
219208 #[ inline]
220209 fn next ( & mut self ) -> Option < <I as Iterator >:: Item > {
221- self . as_inner_mut ( ) . next ( )
210+ unchecked ! ( self ) . next ( )
222211 }
223212
224213 #[ inline]
225214 fn nth ( & mut self , n : usize ) -> Option < I :: Item > {
226- self . as_inner_mut ( ) . nth ( n)
215+ unchecked ! ( self ) . nth ( n)
227216 }
228217
229218 #[ inline]
230219 fn last ( self ) -> Option < I :: Item > {
231- self . into_inner ( ) . last ( )
220+ unchecked ! ( self ) . last ( )
232221 }
233222
234223 #[ inline]
235224 fn count ( self ) -> usize {
236- self . into_inner ( ) . count ( )
225+ unchecked ! ( self ) . count ( )
237226 }
238227
239228 #[ inline]
240229 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
241- self . as_inner ( ) . size_hint ( )
230+ unchecked ! ( self ) . size_hint ( )
242231 }
243232
244233 #[ inline]
@@ -248,23 +237,23 @@ where
248237 Fold : FnMut ( Acc , Self :: Item ) -> R ,
249238 R : Try < Ok = Acc > ,
250239 {
251- self . as_inner_mut ( ) . try_fold ( init, fold)
240+ unchecked ! ( self ) . try_fold ( init, fold)
252241 }
253242
254243 #[ inline]
255244 fn fold < Acc , Fold > ( self , init : Acc , fold : Fold ) -> Acc
256245 where
257246 Fold : FnMut ( Acc , Self :: Item ) -> Acc ,
258247 {
259- self . into_inner ( ) . fold ( init, fold)
248+ unchecked ! ( self ) . fold ( init, fold)
260249 }
261250
262251 #[ inline]
263252 fn find < P > ( & mut self , predicate : P ) -> Option < Self :: Item >
264253 where
265254 P : FnMut ( & Self :: Item ) -> bool ,
266255 {
267- self . as_inner_mut ( ) . find ( predicate)
256+ unchecked ! ( self ) . find ( predicate)
268257 }
269258}
270259
@@ -275,12 +264,12 @@ where
275264{
276265 #[ inline]
277266 fn next_back ( & mut self ) -> Option < <I as Iterator >:: Item > {
278- self . as_inner_mut ( ) . next_back ( )
267+ unchecked ! ( self ) . next_back ( )
279268 }
280269
281270 #[ inline]
282271 fn nth_back ( & mut self , n : usize ) -> Option < <I as Iterator >:: Item > {
283- self . as_inner_mut ( ) . nth_back ( n)
272+ unchecked ! ( self ) . nth_back ( n)
284273 }
285274
286275 #[ inline]
@@ -290,23 +279,23 @@ where
290279 Fold : FnMut ( Acc , Self :: Item ) -> R ,
291280 R : Try < Ok = Acc > ,
292281 {
293- self . as_inner_mut ( ) . try_rfold ( init, fold)
282+ unchecked ! ( self ) . try_rfold ( init, fold)
294283 }
295284
296285 #[ inline]
297286 fn rfold < Acc , Fold > ( self , init : Acc , fold : Fold ) -> Acc
298287 where
299288 Fold : FnMut ( Acc , Self :: Item ) -> Acc ,
300289 {
301- self . into_inner ( ) . rfold ( init, fold)
290+ unchecked ! ( self ) . rfold ( init, fold)
302291 }
303292
304293 #[ inline]
305294 fn rfind < P > ( & mut self , predicate : P ) -> Option < Self :: Item >
306295 where
307296 P : FnMut ( & Self :: Item ) -> bool ,
308297 {
309- self . as_inner_mut ( ) . rfind ( predicate)
298+ unchecked ! ( self ) . rfind ( predicate)
310299 }
311300}
312301
@@ -316,11 +305,11 @@ where
316305 I : ExactSizeIterator + FusedIterator ,
317306{
318307 fn len ( & self ) -> usize {
319- self . as_inner ( ) . len ( )
308+ unchecked ! ( self ) . len ( )
320309 }
321310
322311 fn is_empty ( & self ) -> bool {
323- self . as_inner ( ) . is_empty ( )
312+ unchecked ! ( self ) . is_empty ( )
324313 }
325314}
326315
0 commit comments