@@ -1273,54 +1273,68 @@ unsafe impl<I> TrustedLen for Enumerate<I>
1273
1273
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1274
1274
pub struct Peekable < I : Iterator > {
1275
1275
iter : I ,
1276
- peeked : Option < I :: Item > ,
1276
+ /// Remember a peeked value, even if it was None.
1277
+ peeked : Option < Option < I :: Item > > ,
1277
1278
}
1278
1279
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.
1279
1284
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1280
1285
impl < I : Iterator > Iterator for Peekable < I > {
1281
1286
type Item = I :: Item ;
1282
1287
1283
1288
#[ inline]
1284
1289
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 ,
1287
1292
None => self . iter . next ( ) ,
1288
1293
}
1289
1294
}
1290
1295
1291
1296
#[ inline]
1292
1297
#[ 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
+ }
1295
1304
}
1296
1305
1297
1306
#[ inline]
1298
1307
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) ,
1306
1314
}
1307
1315
}
1308
1316
1309
1317
#[ 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)
1312
1325
}
1313
1326
1314
1327
#[ inline]
1315
1328
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
+ } ;
1316
1334
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)
1324
1338
}
1325
1339
}
1326
1340
@@ -1372,9 +1386,13 @@ impl<I: Iterator> Peekable<I> {
1372
1386
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1373
1387
pub fn peek ( & mut self ) -> Option < & I :: Item > {
1374
1388
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 ! ( ) ,
1376
1395
}
1377
- self . peeked . as_ref ( )
1378
1396
}
1379
1397
}
1380
1398
0 commit comments