Skip to content

Annotate all core iterators with their fusedness #34343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/libcore/char.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,8 @@ impl CharExt for char {
/// This `struct` is created by the [`escape_unicode()`] method on [`char`]. See
/// its documentation for more.
///
/// This iterator is fused.
///
/// [`escape_unicode()`]: ../../std/primitive.char.html#method.escape_unicode
/// [`char`]: ../../std/primitive.char.html
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -505,6 +507,8 @@ impl ExactSizeIterator for EscapeUnicode {
/// This `struct` is created by the [`escape_default()`] method on [`char`]. See
/// its documentation for more.
///
/// This iterator is fused.
///
/// [`escape_default()`]: ../../std/primitive.char.html#method.escape_default
/// [`char`]: ../../std/primitive.char.html
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -604,6 +608,8 @@ impl ExactSizeIterator for EscapeDefault {
/// value.
///
/// Constructed via the `.encode_utf8()` method on `char`.
///
/// This iterator is fused.
#[unstable(feature = "unicode", issue = "27784")]
#[derive(Debug)]
pub struct EncodeUtf8 {
Expand Down Expand Up @@ -642,6 +648,8 @@ impl Iterator for EncodeUtf8 {
/// value.
///
/// Constructed via the `.encode_utf16()` method on `char`.
///
/// This iterator is fused.
#[unstable(feature = "unicode", issue = "27784")]
#[derive(Debug)]
pub struct EncodeUtf16 {
Expand Down
3 changes: 3 additions & 0 deletions src/libcore/iter/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,9 @@ pub trait Iterator {
/// `next` is called on the underlying iterator, hence any side effects of
/// the `next` method will occur.
///
/// If the iterator is exhausted by peeking, calling `next` or `peek` again
/// has unspecified results if the iterator isn't fused.
///
/// [`peek()`]: struct.Peekable.html#method.peek
///
/// # Examples
Expand Down
53 changes: 47 additions & 6 deletions src/libcore/iter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,8 @@ impl<I> ExactSizeIterator for Rev<I>
/// This `struct` is created by the [`cloned()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused if its interior iterator is fused.
///
/// [`cloned()`]: trait.Iterator.html#method.cloned
/// [`Iterator`]: trait.Iterator.html
#[stable(feature = "iter_cloned", since = "1.1.0")]
Expand Down Expand Up @@ -417,6 +419,8 @@ impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
/// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused because it never returns `None`.
///
/// [`cycle()`]: trait.Iterator.html#method.cycle
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -455,6 +459,8 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
/// This `struct` is created by the [`chain()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused.
///
/// [`chain()`]: trait.Iterator.html#method.chain
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
Expand All @@ -476,9 +482,7 @@ pub struct Chain<A, B> {
// - Both: `a` and `b` are remaining
// - Front: `a` remaining
// - Back: `b` remaining
//
// The fourth state (neither iterator is remaining) only occurs after Chain has
// returned None once, so we don't need to store this state.
// - Neither: Neither iterator is remaining.
#[derive(Clone, Debug)]
enum ChainState {
// both front and back iterator are remaining
Expand All @@ -487,6 +491,8 @@ enum ChainState {
Front,
// only back is remaining
Back,
// neither
Neither,
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand All @@ -508,6 +514,7 @@ impl<A, B> Iterator for Chain<A, B> where
},
ChainState::Front => self.a.next(),
ChainState::Back => self.b.next(),
ChainState::Neither => None,
}
}

Expand All @@ -518,6 +525,7 @@ impl<A, B> Iterator for Chain<A, B> where
ChainState::Both => self.a.count() + self.b.count(),
ChainState::Front => self.a.count(),
ChainState::Back => self.b.count(),
ChainState::Neither => 0,
}
}

Expand All @@ -536,6 +544,7 @@ impl<A, B> Iterator for Chain<A, B> where
}
}
ChainState::Back => {}
ChainState::Neither => return None,
}
if let ChainState::Back = self.state {
self.b.nth(n)
Expand All @@ -558,6 +567,7 @@ impl<A, B> Iterator for Chain<A, B> where
},
ChainState::Front => self.a.find(predicate),
ChainState::Back => self.b.find(predicate),
ChainState::Neither => None,
}
}

Expand All @@ -571,12 +581,19 @@ impl<A, B> Iterator for Chain<A, B> where
b_last.or(a_last)
},
ChainState::Front => self.a.last(),
ChainState::Back => self.b.last()
ChainState::Back => self.b.last(),
ChainState::Neither => None,
}
}

#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self.state {
ChainState::Both => {},
ChainState::Front => return self.a.size_hint(),
ChainState::Back => return self.b.size_hint(),
ChainState::Neither => return (0, Some(0)),
}
let (a_lower, a_upper) = self.a.size_hint();
let (b_lower, b_upper) = self.b.size_hint();

Expand Down Expand Up @@ -608,6 +625,7 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
},
ChainState::Front => self.a.next_back(),
ChainState::Back => self.b.next_back(),
ChainState::Neither => None,
}
}
}
Expand All @@ -617,6 +635,8 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
/// This `struct` is created by the [`zip()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused if both interior iterators are fused.
///
/// [`zip()`]: trait.Iterator.html#method.zip
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
Expand All @@ -629,8 +649,7 @@ pub struct Zip<A, B> {
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A, B> Iterator for Zip<A, B> where A: Iterator, B: Iterator
{
impl<A, B> Iterator for Zip<A, B> where A: Iterator, B: Iterator {
type Item = (A::Item, B::Item);

#[inline]
Expand Down Expand Up @@ -872,6 +891,8 @@ unsafe impl<A, B> TrustedRandomAccess for Zip<A, B>
/// println!("{:?}", pair);
/// }
/// ```
///
/// This iterator is fused if its interior iterator is fused.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
Expand Down Expand Up @@ -923,6 +944,8 @@ impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
/// This `struct` is created by the [`filter()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused if its interior iterator is fused.
///
/// [`filter()`]: trait.Iterator.html#method.filter
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
Expand Down Expand Up @@ -983,6 +1006,8 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
/// This `struct` is created by the [`filter_map()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused if its interior iterator is fused.
///
/// [`filter_map()`]: trait.Iterator.html#method.filter_map
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
Expand Down Expand Up @@ -1045,6 +1070,8 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
/// This `struct` is created by the [`enumerate()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused if its interior iterator is fused.
///
/// [`enumerate()`]: trait.Iterator.html#method.enumerate
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -1133,6 +1160,8 @@ unsafe impl<I> TrustedRandomAccess for Enumerate<I>
/// This `struct` is created by the [`peekable()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused if its interior iterator is fused.
///
/// [`peekable()`]: trait.Iterator.html#method.peekable
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -1335,6 +1364,8 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P>
/// This `struct` is created by the [`take_while()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused if its interior iterator is fused.
///
/// [`take_while()`]: trait.Iterator.html#method.take_while
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
Expand Down Expand Up @@ -1390,6 +1421,8 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P>
/// This `struct` is created by the [`skip()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused if its interior iterator is fused.
///
/// [`skip()`]: trait.Iterator.html#method.skip
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -1481,6 +1514,8 @@ impl<I> DoubleEndedIterator for Skip<I> where I: DoubleEndedIterator + ExactSize
/// This `struct` is created by the [`take()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused.
///
/// [`take()`]: trait.Iterator.html#method.take
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -1543,6 +1578,8 @@ impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}
/// This `struct` is created by the [`scan()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused if its interior iterator is fused.
///
/// [`scan()`]: trait.Iterator.html#method.scan
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
Expand Down Expand Up @@ -1589,6 +1626,8 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where
/// This `struct` is created by the [`flat_map()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused if the iterator yielding the iterators is fused.
///
/// [`flat_map()`]: trait.Iterator.html#method.flat_map
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
Expand Down Expand Up @@ -1675,6 +1714,8 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher
/// This `struct` is created by the [`fuse()`] method on [`Iterator`]. See its
/// documentation for more.
///
/// This iterator is fused.
///
/// [`fuse()`]: trait.Iterator.html#method.fuse
/// [`Iterator`]: trait.Iterator.html
#[derive(Clone, Debug)]
Expand Down
2 changes: 2 additions & 0 deletions src/libcore/iter/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ step_impl_no_between!(u64 i64);
/// The resulting iterator handles overflow by stopping. The `A`
/// parameter is the type being iterated over, while `R` is the range
/// type (usually one of `std::ops::{Range, RangeFrom, RangeInclusive}`.
///
/// This iterator is fused if the underlying range iterator is fused.
#[derive(Clone, Debug)]
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
Expand Down
6 changes: 6 additions & 0 deletions src/libcore/iter/sources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use super::{DoubleEndedIterator, IntoIterator, Iterator, ExactSizeIterator};
///
/// This `struct` is created by the [`repeat()`] function. See its documentation for more.
///
/// This iterator is fused because it never returns `None`.
///
/// [`repeat()`]: fn.repeat.html
#[derive(Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down Expand Up @@ -100,6 +102,8 @@ pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
///
/// This `struct` is created by the [`empty()`] function. See its documentation for more.
///
/// This iterator is fused.
///
/// [`empty()`]: fn.empty.html
#[stable(feature = "iter_empty", since = "1.2.0")]
pub struct Empty<T>(marker::PhantomData<T>);
Expand Down Expand Up @@ -179,6 +183,8 @@ pub fn empty<T>() -> Empty<T> {
///
/// This `struct` is created by the [`once()`] function. See its documentation for more.
///
/// This iterator is fused.
///
/// [`once()`]: fn.once.html
#[derive(Clone, Debug)]
#[stable(feature = "iter_once", since = "1.2.0")]
Expand Down
6 changes: 6 additions & 0 deletions src/libcore/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,8 @@ impl fmt::Debug for RangeFull {
/// A (half-open) range which is bounded at both ends: { x | start <= x < end }.
/// Use `start..end` (two dots) for its shorthand.
///
/// This iterator is fused.
///
/// See the [`contains()`](#method.contains) method for its characterization.
///
/// # Examples
Expand Down Expand Up @@ -1555,6 +1557,8 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// might panic in debug mode or create an endless loop in release mode. This
/// overflow behavior might change in the future.
///
/// This iterator is fused because it never returns `None`.
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -1654,6 +1658,8 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// An inclusive range which is bounded at both ends: { x | start <= x <= end }.
/// Use `start...end` (three dots) for its shorthand.
///
/// This iterator is fused.
///
/// See the [`contains()`](#method.contains) method for its characterization.
///
/// # Examples
Expand Down
6 changes: 6 additions & 0 deletions src/libcore/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,8 @@ impl<A> DoubleEndedIterator for Item<A> {
impl<A> ExactSizeIterator for Item<A> {}

/// An iterator over a reference of the contained item in an Option.
///
/// This iterator is fused.
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Iter<'a, A: 'a> { inner: Item<&'a A> }
Expand Down Expand Up @@ -821,6 +823,8 @@ impl<'a, A> Clone for Iter<'a, A> {
}

/// An iterator over a mutable reference of the contained item in an Option.
///
/// This iterator is fused.
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct IterMut<'a, A: 'a> { inner: Item<&'a mut A> }
Expand All @@ -845,6 +849,8 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
impl<'a, A> ExactSizeIterator for IterMut<'a, A> {}

/// An iterator over the item contained inside an Option.
///
/// This iterator is fused.
#[derive(Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<A> { inner: Item<A> }
Expand Down
6 changes: 6 additions & 0 deletions src/libcore/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,8 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
/////////////////////////////////////////////////////////////////////////////

/// An iterator over a reference to the `Ok` variant of a `Result`.
///
/// This iterator is fused.
#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, T: 'a> { inner: Option<&'a T> }
Expand Down Expand Up @@ -872,6 +874,8 @@ impl<'a, T> Clone for Iter<'a, T> {
}

/// An iterator over a mutable reference to the `Ok` variant of a `Result`.
///
/// This iterator is fused.
#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IterMut<'a, T: 'a> { inner: Option<&'a mut T> }
Expand Down Expand Up @@ -899,6 +903,8 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}

/// An iterator over the value in a `Ok` variant of a `Result`.
///
/// This iterator is fused.
#[derive(Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> { inner: Option<T> }
Expand Down
Loading