Skip to content

Commit 6c9f840

Browse files
committed
Auto merge of #23894 - tbu-:pr_iter_length_position, r=pnkfelix
Added documentation of the panicking overflow to the `count` and `position` methods of `IteratorExt`, also make them more obvious in the code. Also mention that the `Iterator::next` method of the struct returned by `IteratorExt::enumerate` can panic due to overflow.
2 parents e6378cb + 29d7fed commit 6c9f840

File tree

1 file changed

+58
-6
lines changed

1 file changed

+58
-6
lines changed

src/libcore/iter.rs

+58-6
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,18 @@ pub trait Iterator {
106106

107107
/// Counts the number of elements in this iterator.
108108
///
109+
/// # Overflow Behavior
110+
///
111+
/// The method does no guarding against overflows, so counting elements of
112+
/// an iterator with more than `usize::MAX` elements either produces the
113+
/// wrong result or panics. If debug assertions are enabled, a panic is
114+
/// guaranteed.
115+
///
116+
/// # Panics
117+
///
118+
/// This functions might panic if the iterator has more than `usize::MAX`
119+
/// elements.
120+
///
109121
/// # Examples
110122
///
111123
/// ```
@@ -115,7 +127,8 @@ pub trait Iterator {
115127
#[inline]
116128
#[stable(feature = "rust1", since = "1.0.0")]
117129
fn count(self) -> usize where Self: Sized {
118-
self.fold(0, |cnt, _x| cnt + 1)
130+
// Might overflow.
131+
self.fold(0, |cnt, _| cnt + 1)
119132
}
120133

121134
/// Loops through the entire iterator, returning the last element.
@@ -281,6 +294,17 @@ pub trait Iterator {
281294
/// different sized integer, the `zip` function provides similar
282295
/// functionality.
283296
///
297+
/// # Overflow Behavior
298+
///
299+
/// The method does no guarding against overflows, so enumerating more than
300+
/// `usize::MAX` elements either produces the wrong result or panics. If
301+
/// debug assertions are enabled, a panic is guaranteed.
302+
///
303+
/// # Panics
304+
///
305+
/// The returned iterator might panic if the to-be-returned index would
306+
/// overflow a `usize`.
307+
///
284308
/// # Examples
285309
///
286310
/// ```
@@ -293,7 +317,7 @@ pub trait Iterator {
293317
#[inline]
294318
#[stable(feature = "rust1", since = "1.0.0")]
295319
fn enumerate(self) -> Enumerate<Self> where Self: Sized {
296-
Enumerate{iter: self, count: 0}
320+
Enumerate { iter: self, count: 0 }
297321
}
298322

299323
/// Creates an iterator that has a `.peek()` method
@@ -672,6 +696,18 @@ pub trait Iterator {
672696
///
673697
/// Does not consume the iterator past the first found element.
674698
///
699+
/// # Overflow Behavior
700+
///
701+
/// The method does no guarding against overflows, so if there are more
702+
/// than `usize::MAX` non-matching elements, it either produces the wrong
703+
/// result or panics. If debug assertions are enabled, a panic is
704+
/// guaranteed.
705+
///
706+
/// # Panics
707+
///
708+
/// This functions might panic if the iterator has more than `usize::MAX`
709+
/// non-matching elements.
710+
///
675711
/// # Examples
676712
///
677713
/// ```
@@ -685,12 +721,11 @@ pub trait Iterator {
685721
Self: Sized,
686722
P: FnMut(Self::Item) -> bool,
687723
{
688-
let mut i = 0;
689-
for x in self.by_ref() {
724+
// `enumerate` might overflow.
725+
for (i, x) in self.by_ref().enumerate() {
690726
if predicate(x) {
691727
return Some(i);
692728
}
693-
i += 1;
694729
}
695730
None
696731
}
@@ -720,6 +755,8 @@ pub trait Iterator {
720755
if predicate(v) {
721756
return Some(i - 1);
722757
}
758+
// No need for an overflow check here, because `ExactSizeIterator`
759+
// implies that the number of elements fits into a `usize`.
723760
i -= 1;
724761
}
725762
None
@@ -1783,17 +1820,27 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
17831820
#[stable(feature = "rust1", since = "1.0.0")]
17841821
pub struct Enumerate<I> {
17851822
iter: I,
1786-
count: usize
1823+
count: usize,
17871824
}
17881825

17891826
#[stable(feature = "rust1", since = "1.0.0")]
17901827
impl<I> Iterator for Enumerate<I> where I: Iterator {
17911828
type Item = (usize, <I as Iterator>::Item);
17921829

1830+
/// # Overflow Behavior
1831+
///
1832+
/// The method does no guarding against overflows, so enumerating more than
1833+
/// `usize::MAX` elements either produces the wrong result or panics. If
1834+
/// debug assertions are enabled, a panic is guaranteed.
1835+
///
1836+
/// # Panics
1837+
///
1838+
/// Might panic if the index of the element overflows a `usize`.
17931839
#[inline]
17941840
fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
17951841
self.iter.next().map(|a| {
17961842
let ret = (self.count, a);
1843+
// Possible undefined overflow.
17971844
self.count += 1;
17981845
ret
17991846
})
@@ -1827,6 +1874,8 @@ impl<I> DoubleEndedIterator for Enumerate<I> where
18271874
fn next_back(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
18281875
self.iter.next_back().map(|a| {
18291876
let len = self.iter.len();
1877+
// Can safely add, `ExactSizeIterator` promises that the number of
1878+
// elements fits into a `usize`.
18301879
(self.count + len, a)
18311880
})
18321881
}
@@ -1841,6 +1890,9 @@ impl<I> RandomAccessIterator for Enumerate<I> where I: RandomAccessIterator {
18411890

18421891
#[inline]
18431892
fn idx(&mut self, index: usize) -> Option<(usize, <I as Iterator>::Item)> {
1893+
// Can safely add, `ExactSizeIterator` (ancestor of
1894+
// `RandomAccessIterator`) promises that the number of elements fits
1895+
// into a `usize`.
18441896
self.iter.idx(index).map(|a| (self.count + index, a))
18451897
}
18461898
}

0 commit comments

Comments
 (0)