@@ -1273,54 +1273,68 @@ unsafe impl<I> TrustedLen for Enumerate<I>
12731273#[ stable( feature = "rust1" , since = "1.0.0" ) ]
12741274pub struct Peekable < I : Iterator > {
12751275 iter : I ,
1276- peeked : Option < I :: Item > ,
1276+ /// Remember a peeked value, even if it was None.
1277+ peeked : Option < Option < I :: Item > > ,
12771278}
12781279
1280+ // Peekable must remember if a None has been seen in the `.peek()` method.
1281+ // It ensures that `.peek(); .peek();` or `.peek(); .next();` only advances the
1282+ // underlying iterator at most once. This does not by itself make the iterator
1283+ // fused.
12791284#[ stable( feature = "rust1" , since = "1.0.0" ) ]
12801285impl < I : Iterator > Iterator for Peekable < I > {
12811286 type Item = I :: Item ;
12821287
12831288 #[ inline]
12841289 fn next ( & mut self ) -> Option < I :: Item > {
1285- match self . peeked {
1286- Some ( _ ) => self . peeked . take ( ) ,
1290+ match self . peeked . take ( ) {
1291+ Some ( v ) => v ,
12871292 None => self . iter . next ( ) ,
12881293 }
12891294 }
12901295
12911296 #[ inline]
12921297 #[ rustc_inherit_overflow_checks]
1293- fn count ( self ) -> usize {
1294- ( if self . peeked . is_some ( ) { 1 } else { 0 } ) + self . iter . count ( )
1298+ fn count ( mut self ) -> usize {
1299+ match self . peeked . take ( ) {
1300+ Some ( None ) => 0 ,
1301+ Some ( Some ( _) ) => 1 + self . iter . count ( ) ,
1302+ None => self . iter . count ( ) ,
1303+ }
12951304 }
12961305
12971306 #[ inline]
12981307 fn nth ( & mut self , n : usize ) -> Option < I :: Item > {
1299- match self . peeked {
1300- Some ( _) if n == 0 => self . peeked . take ( ) ,
1301- Some ( _) => {
1302- self . peeked = None ;
1303- self . iter . nth ( n-1 )
1304- } ,
1305- None => self . iter . nth ( n)
1308+ match self . peeked . take ( ) {
1309+ // the .take() below is just to avoid "move into pattern guard"
1310+ Some ( ref mut v) if n == 0 => v. take ( ) ,
1311+ Some ( None ) => None ,
1312+ Some ( Some ( _) ) => self . iter . nth ( n - 1 ) ,
1313+ None => self . iter . nth ( n) ,
13061314 }
13071315 }
13081316
13091317 #[ inline]
1310- fn last ( self ) -> Option < I :: Item > {
1311- self . iter . last ( ) . or ( self . peeked )
1318+ fn last ( mut self ) -> Option < I :: Item > {
1319+ let peek_opt = match self . peeked . take ( ) {
1320+ Some ( None ) => return None ,
1321+ Some ( v) => v,
1322+ None => None ,
1323+ } ;
1324+ self . iter . last ( ) . or ( peek_opt)
13121325 }
13131326
13141327 #[ inline]
13151328 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1329+ let peek_len = match self . peeked {
1330+ Some ( None ) => return ( 0 , Some ( 0 ) ) ,
1331+ Some ( Some ( _) ) => 1 ,
1332+ None => 0 ,
1333+ } ;
13161334 let ( lo, hi) = self . iter . size_hint ( ) ;
1317- if self . peeked . is_some ( ) {
1318- let lo = lo. saturating_add ( 1 ) ;
1319- let hi = hi. and_then ( |x| x. checked_add ( 1 ) ) ;
1320- ( lo, hi)
1321- } else {
1322- ( lo, hi)
1323- }
1335+ let lo = lo. saturating_add ( peek_len) ;
1336+ let hi = hi. and_then ( |x| x. checked_add ( peek_len) ) ;
1337+ ( lo, hi)
13241338 }
13251339}
13261340
@@ -1372,9 +1386,13 @@ impl<I: Iterator> Peekable<I> {
13721386 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
13731387 pub fn peek ( & mut self ) -> Option < & I :: Item > {
13741388 if self . peeked . is_none ( ) {
1375- self . peeked = self . iter . next ( ) ;
1389+ self . peeked = Some ( self . iter . next ( ) ) ;
1390+ }
1391+ match self . peeked {
1392+ Some ( Some ( ref value) ) => Some ( value) ,
1393+ Some ( None ) => None ,
1394+ _ => unreachable ! ( ) ,
13761395 }
1377- self . peeked . as_ref ( )
13781396 }
13791397}
13801398
0 commit comments