@@ -298,9 +298,9 @@ range_incl_exact_iter_impl! {
298298#[ derive( Debug , Clone ) ]
299299pub struct RangeFromIter < A > {
300300 start : A ,
301- /// Whether the first element of the iterator has yielded.
301+ /// Whether the maximum value of the iterator has yielded.
302302 /// Only used when overflow checks are enabled.
303- first : bool ,
303+ exhausted : bool ,
304304}
305305
306306impl < A : Step > RangeFromIter < A > {
@@ -309,10 +309,12 @@ impl<A: Step> RangeFromIter<A> {
309309 #[ rustc_inherit_overflow_checks]
310310 #[ unstable( feature = "new_range_api" , issue = "125687" ) ]
311311 pub fn remainder ( self ) -> RangeFrom < A > {
312- if intrinsics:: overflow_checks ( ) {
313- if !self . first {
314- return RangeFrom { start : Step :: forward ( self . start , 1 ) } ;
315- }
312+ // Need to handle this case even if overflow-checks are disabled,
313+ // because a `RangeFromIter` could be exhausted in a crate with
314+ // overflow-checks enabled, but then passed to a crate with them
315+ // disabled before this is called.
316+ if self . exhausted {
317+ return RangeFrom { start : Step :: forward ( self . start , 1 ) } ;
316318 }
317319
318320 RangeFrom { start : self . start }
@@ -326,14 +328,29 @@ impl<A: Step> Iterator for RangeFromIter<A> {
326328 #[ inline]
327329 #[ rustc_inherit_overflow_checks]
328330 fn next ( & mut self ) -> Option < A > {
331+ if self . exhausted {
332+ // This should panic if overflow checks are enabled, since
333+ // `forward_checked` returned `None` in prior iteration.
334+ self . start = Step :: forward ( self . start . clone ( ) , 1 ) ;
335+
336+ // If we get here, if means this iterator was exhausted by a crate
337+ // with overflow-checks enabled, but now we're iterating in a crate with
338+ // overflow-checks disabled. Since we successfully incremented `self.start`
339+ // above (in many cases this will wrap around to MIN), we now unset
340+ // the flag so we don't repeat this process in the next iteration.
341+ //
342+ // This could also happen if `forward_checked` returned None but
343+ // (for whatever reason, not applicable to any std implementors)
344+ // `forward` doesn't panic when overflow-checks are enabled. In that
345+ // case, this is also the correct behavior.
346+ self . exhausted = false ;
347+ }
329348 if intrinsics:: overflow_checks ( ) {
330- if self . first {
331- self . first = false ;
349+ let Some ( n ) = Step :: forward_checked ( self . start . clone ( ) , 1 ) else {
350+ self . exhausted = true ;
332351 return Some ( self . start . clone ( ) ) ;
333- }
334-
335- self . start = Step :: forward ( self . start . clone ( ) , 1 ) ;
336- return Some ( self . start . clone ( ) ) ;
352+ } ;
353+ return Some ( mem:: replace ( & mut self . start , n) ) ;
337354 }
338355
339356 let n = Step :: forward ( self . start . clone ( ) , 1 ) ;
@@ -348,18 +365,22 @@ impl<A: Step> Iterator for RangeFromIter<A> {
348365 #[ inline]
349366 #[ rustc_inherit_overflow_checks]
350367 fn nth ( & mut self , n : usize ) -> Option < A > {
368+ // Typically `forward` will cause an overflow-check panic here,
369+ // but unset the exhausted flag to handle the uncommon cases.
370+ // See the comments in `next` for more details.
371+ if self . exhausted {
372+ self . start = Step :: forward ( self . start . clone ( ) , 1 ) ;
373+ self . exhausted = false ;
374+ }
351375 if intrinsics:: overflow_checks ( ) {
352- if self . first {
353- self . first = false ;
354-
355- let plus_n = Step :: forward ( self . start . clone ( ) , n ) ;
376+ let plus_n = Step :: forward ( self . start . clone ( ) , n ) ;
377+ if let Some ( plus_n1 ) = Step :: forward_checked ( plus_n . clone ( ) , 1 ) {
378+ self . start = plus_n1 ;
379+ } else {
356380 self . start = plus_n. clone ( ) ;
357- return Some ( plus_n ) ;
381+ self . exhausted = true ;
358382 }
359-
360- let plus_n = Step :: forward ( self . start . clone ( ) , n) ;
361- self . start = Step :: forward ( plus_n. clone ( ) , 1 ) ;
362- return Some ( self . start . clone ( ) ) ;
383+ return Some ( plus_n) ;
363384 }
364385
365386 let plus_n = Step :: forward ( self . start . clone ( ) , n) ;
@@ -380,6 +401,6 @@ impl<A: Step> IntoIterator for RangeFrom<A> {
380401 type IntoIter = RangeFromIter < A > ;
381402
382403 fn into_iter ( self ) -> Self :: IntoIter {
383- RangeFromIter { start : self . start , first : true }
404+ RangeFromIter { start : self . start , exhausted : false }
384405 }
385406}
0 commit comments