@@ -18,6 +18,9 @@ pub struct Chain<A, B> {
1818 // adapter because its specialization for `FusedIterator` unconditionally descends into the
1919 // iterator, and that could be expensive to keep revisiting stuff like nested chains. It also
2020 // hurts compiler performance to add more iterator layers to `Chain`.
21+ //
22+ // Only the "first" iterator is actually set `None` when exhausted, depending on whether you
23+ // iterate forward or backward. If you mix directions, then both sides may be `None`.
2124 a : Option < A > ,
2225 b : Option < B > ,
2326}
@@ -43,6 +46,17 @@ macro_rules! fuse {
4346 } ;
4447}
4548
49+ /// Try an iterator method without fusing,
50+ /// like an inline `.as_mut().and_then(...)`
51+ macro_rules! maybe {
52+ ( $self: ident . $iter: ident . $( $call: tt) +) => {
53+ match $self. $iter {
54+ Some ( ref mut iter) => iter. $( $call) +,
55+ None => None ,
56+ }
57+ } ;
58+ }
59+
4660#[ stable( feature = "rust1" , since = "1.0.0" ) ]
4761impl < A , B > Iterator for Chain < A , B >
4862where
5468 #[ inline]
5569 fn next ( & mut self ) -> Option < A :: Item > {
5670 match fuse ! ( self . a. next( ) ) {
57- None => fuse ! ( self . b. next( ) ) ,
71+ None => maybe ! ( self . b. next( ) ) ,
5872 item => item,
5973 }
6074 }
8599 }
86100 if let Some ( ref mut b) = self . b {
87101 acc = b. try_fold ( acc, f) ?;
88- self . b = None ;
102+ // we don't fuse the second iterator
89103 }
90104 Try :: from_ok ( acc)
91105 }
@@ -114,7 +128,7 @@ where
114128 }
115129 self . a = None ;
116130 }
117- fuse ! ( self . b. nth( n) )
131+ maybe ! ( self . b. nth( n) )
118132 }
119133
120134 #[ inline]
@@ -123,7 +137,7 @@ where
123137 P : FnMut ( & Self :: Item ) -> bool ,
124138 {
125139 match fuse ! ( self . a. find( & mut predicate) ) {
126- None => fuse ! ( self . b. find( predicate) ) ,
140+ None => maybe ! ( self . b. find( predicate) ) ,
127141 item => item,
128142 }
129143 }
@@ -174,7 +188,7 @@ where
174188 #[ inline]
175189 fn next_back ( & mut self ) -> Option < A :: Item > {
176190 match fuse ! ( self . b. next_back( ) ) {
177- None => fuse ! ( self . a. next_back( ) ) ,
191+ None => maybe ! ( self . a. next_back( ) ) ,
178192 item => item,
179193 }
180194 }
@@ -190,7 +204,7 @@ where
190204 }
191205 self . b = None ;
192206 }
193- fuse ! ( self . a. nth_back( n) )
207+ maybe ! ( self . a. nth_back( n) )
194208 }
195209
196210 #[ inline]
@@ -199,7 +213,7 @@ where
199213 P : FnMut ( & Self :: Item ) -> bool ,
200214 {
201215 match fuse ! ( self . b. rfind( & mut predicate) ) {
202- None => fuse ! ( self . a. rfind( predicate) ) ,
216+ None => maybe ! ( self . a. rfind( predicate) ) ,
203217 item => item,
204218 }
205219 }
@@ -216,7 +230,7 @@ where
216230 }
217231 if let Some ( ref mut a) = self . a {
218232 acc = a. try_rfold ( acc, f) ?;
219- self . a = None ;
233+ // we don't fuse the second iterator
220234 }
221235 Try :: from_ok ( acc)
222236 }
@@ -236,8 +250,6 @@ where
236250}
237251
238252// Note: *both* must be fused to handle double-ended iterators.
239- // Now that we "fuse" both sides, we *could* implement this unconditionally,
240- // but we should be cautious about committing to that in the public API.
241253#[ stable( feature = "fused" , since = "1.26.0" ) ]
242254impl < A , B > FusedIterator for Chain < A , B >
243255where
0 commit comments