diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6f125cdba8190..065d6a6263bfe 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -63,7 +63,7 @@ use core::borrow; use core::cmp::Ordering; use core::fmt; use core::hash::{self, Hash, Hasher}; -use core::iter::FusedIterator; +use core::iter::{FusedIterator, UnboundedIterator}; use core::marker::{self, Unsize}; use core::mem; use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState}; @@ -759,6 +759,9 @@ impl ExactSizeIterator for Box { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Box {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Box {} + /// `FnBox` is a version of the `FnOnce` intended for use with boxed /// closure objects. The idea is that where one would normally store a diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 3cc3ea467966b..04af4355e5569 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -118,6 +118,7 @@ #![feature(staged_api)] #![feature(str_internals)] #![feature(trusted_len)] +#![feature(unbounded_iter)] #![feature(unboxed_closures)] #![feature(unicode)] #![feature(unique)] diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 06c29b47bf921..97d8343af8e95 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -331,6 +331,11 @@ pub use self::traits::{ExactSizeIterator, Sum, Product}; pub use self::traits::FusedIterator; #[unstable(feature = "trusted_len", issue = "37572")] pub use self::traits::TrustedLen; +#[unstable(feature = "unbounded_iter", issue = "0")] +pub use self::traits::UnboundedIterator; +// FIXME: #46813 +//#[unstable(feature = "unbounded_iter", issue = "0")] +//pub use self::traits::UnboundedIteratorAuto; mod iterator; mod range; @@ -497,6 +502,10 @@ impl FusedIterator for Rev unsafe impl TrustedLen for Rev where I: TrustedLen + DoubleEndedIterator {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Rev + where I: UnboundedIterator + DoubleEndedIterator {} + /// An iterator that clones the elements of an underlying iterator. /// /// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its @@ -577,6 +586,10 @@ impl<'a, I, T: 'a> FusedIterator for Cloned where I: FusedIterator, T: Clone {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl<'a, I, T: 'a> UnboundedIterator for Cloned + where I: UnboundedIterator, T: Clone {} + #[doc(hidden)] default unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned where I: TrustedRandomAccess, T: Clone @@ -628,6 +641,30 @@ impl Iterator for Cycle where I: Clone + Iterator { #[inline] fn next(&mut self) -> Option<::Item> { + CycleImpl::next(self) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + CycleImpl::size_hint(self) + } +} + +// Cycle specialization trait +// FIXME: #36262 +#[doc(hidden)] +trait CycleImpl { + type Item; + fn next(&mut self) -> Option; + fn size_hint(&self) -> (usize, Option); +} + +// General Cycle impl +impl CycleImpl for Cycle where I: Clone + Iterator { + type Item = ::Item; + + #[inline] + default fn next(&mut self) -> Option { match self.iter.next() { None => { self.iter = self.orig.clone(); self.iter.next() } y => y @@ -635,7 +672,7 @@ impl Iterator for Cycle where I: Clone + Iterator { } #[inline] - fn size_hint(&self) -> (usize, Option) { + default fn size_hint(&self) -> (usize, Option) { // the cycle iterator is either empty or infinite match self.orig.size_hint() { sz @ (0, Some(0)) => sz, @@ -645,9 +682,28 @@ impl Iterator for Cycle where I: Clone + Iterator { } } +// Specialized Cycle impl for an underlying UnboundedIterator +impl CycleImpl for Cycle where I: Clone + UnboundedIterator { + #[inline] + fn next(&mut self) -> Option { + self.iter.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } +} + #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Cycle where I: Clone + Iterator {} +// We can't implement `UnboundedIterator` for all `Cycle`. +// If the underlying iterator returns `None` as first element, it would +// break the contract. +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Cycle where I: Clone + UnboundedIterator {} + /// An iterator for stepping iterators by a custom amount. /// /// This `struct` is created by the [`step_by`] method on [`Iterator`]. See @@ -684,6 +740,21 @@ impl Iterator for StepBy where I: Iterator { #[inline] fn size_hint(&self) -> (usize, Option) { + StepByImpl::size_hint(self) + } +} + +// StepBy specialization trait +// FIXME: #36262 +#[doc(hidden)] +trait StepByImpl { + fn size_hint(&self) -> (usize, Option); +} + +// General StepBy impl +impl StepByImpl for StepBy { + #[inline] + default fn size_hint(&self) -> (usize, Option) { let inner_hint = self.iter.size_hint(); if self.first_take { @@ -696,12 +767,31 @@ impl Iterator for StepBy where I: Iterator { } } +// Specialized StepBy impl for an underlying UnboundedIterator +impl StepByImpl for StepBy { + #[inline] + fn size_hint(&self) -> (usize, Option) { + // We step over some of the infinitely many elements. + (usize::MAX, None) + } +} + // StepBy can only make the iterator shorter, so the len will still fit. #[unstable(feature = "iterator_step_by", reason = "unstable replacement of Range::step_by", issue = "27741")] impl ExactSizeIterator for StepBy where I: ExactSizeIterator {} +#[unstable(feature = "iterator_step_by", + reason = "unstable replacement of Range::step_by", + issue = "27741")] +impl FusedIterator for StepBy where I: FusedIterator {} + +#[unstable(feature = "iterator_step_by", + reason = "unstable replacement of Range::step_by", + issue = "27741")] +unsafe impl UnboundedIterator for StepBy {} + /// An iterator that strings two iterators together. /// /// This `struct` is created by the [`chain`] method on [`Iterator`]. See its @@ -867,17 +957,7 @@ impl Iterator for Chain where #[inline] fn size_hint(&self) -> (usize, Option) { - let (a_lower, a_upper) = self.a.size_hint(); - let (b_lower, b_upper) = self.b.size_hint(); - - let lower = a_lower.saturating_add(b_lower); - - let upper = match (a_upper, b_upper) { - (Some(x), Some(y)) => x.checked_add(y), - _ => None - }; - - (lower, upper) + ChainImpl::size_hint(self) } } @@ -941,6 +1021,65 @@ impl DoubleEndedIterator for Chain where } +// Chain specialization trait +// FIXME: #36262 +#[doc(hidden)] +trait ChainImpl { + fn size_hint(&self) -> (usize, Option); +} + +// General Chain impl +#[doc(hidden)] +impl ChainImpl for Chain { + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let (a_lower, a_upper) = self.a.size_hint(); + let (b_lower, b_upper) = self.b.size_hint(); + + let lower = a_lower.saturating_add(b_lower); + + let upper = match (a_upper, b_upper) { + (Some(x), Some(y)) => x.checked_add(y), + _ => None + }; + + (lower, upper) + } +} + +// Specialized Chain impls for underlying UnboundedIterators +// If A or B or both are unbounded, the chain will be unbounded as well. +// FIXME: #46813 +#[doc(hidden)] +impl ChainImpl for Chain + where A: UnboundedIterator, + B: Iterator, +// (A, B): UnboundedIteratorAuto +{ + #[inline] + fn size_hint(&self) -> (usize, Option) { + (usize::MAX, None) + } +} +//#[doc(hidden)] +//impl ChainImpl for Chain +// where B: UnboundedIterator, (A, B): UnboundedIteratorAuto +//{ +// #[inline] +// fn size_hint(&self) -> (usize, Option) { +// (usize::MAX, None) +// } +//} +//#[doc(hidden)] +//impl ChainImpl for Chain +// where A: UnboundedIterator, B: UnboundedIterator +//{ +// #[inline] +// fn size_hint(&self) -> (usize, Option) { +// (usize::MAX, None) +// } +//} + // Note: *both* must be fused to handle double-ended iterators. #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Chain @@ -953,6 +1092,25 @@ unsafe impl TrustedLen for Chain where A: TrustedLen, B: TrustedLen, {} +// FIXME: #46813 +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Chain + where A: UnboundedIterator, + B: FusedIterator, +// (A, B): UnboundedIteratorAuto +{} +//#[unstable(feature = "unbounded_iter", issue = "0")] +//unsafe impl UnboundedIterator for Chain +// where A: Iterator, +// B: UnboundedIterator, +// (A, B): UnboundedIteratorAuto +//{} +//#[unstable(feature = "unbounded_iter", issue = "0")] +//unsafe impl UnboundedIterator for Chain +// where A: UnboundedIterator, +// B: UnboundedIterator +//{} + /// An iterator that iterates two other iterators simultaneously. /// /// This `struct` is created by the [`zip`] method on [`Iterator`]. See its @@ -1175,6 +1333,10 @@ unsafe impl TrustedLen for Zip where A: TrustedLen, B: TrustedLen, {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Zip + where A: UnboundedIterator, B: UnboundedIterator {} + /// An iterator that maps the values of `iter` with `f`. /// /// This `struct` is created by the [`map`] method on [`Iterator`]. See its @@ -1317,6 +1479,11 @@ unsafe impl TrustedLen for Map where I: TrustedLen, F: FnMut(I::Item) -> B {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Map + where I: UnboundedIterator, + F: FnMut(I::Item) -> B {} + #[doc(hidden)] unsafe impl TrustedRandomAccess for Map where I: TrustedRandomAccess, @@ -1369,8 +1536,7 @@ impl Iterator for Filter where P: FnMut(&I::Item) -> bool #[inline] fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate + FilterImpl::size_hint(self) } // this special case allows the compiler to make `.filter(_).count()` @@ -1457,10 +1623,46 @@ impl DoubleEndedIterator for Filter } } +// Filter specialization trait +// FIXME: #36262 +#[doc(hidden)] +trait FilterImpl { + fn size_hint(&self) -> (usize, Option); +} + +// General Filter impl +#[doc(hidden)] +impl FilterImpl for Filter + where P: FnMut(&I::Item) -> bool +{ + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } +} + +// Specialized Filter impl for an underlying UnboundedIterator +#[doc(hidden)] +impl FilterImpl for Filter + where P: FnMut(&I::Item) -> bool +{ + #[inline] + fn size_hint(&self) -> (usize, Option) { + // If the underlying iterator is unbounded, we will either filter out all items + // and thus diverge, or filter out some of the infinitely many items. + (usize::MAX, None) + } +} + #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Filter where P: FnMut(&I::Item) -> bool {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Filter + where P: FnMut(&I::Item) -> bool {} + /// An iterator that uses `f` to both filter and map elements from `iter`. /// /// This `struct` is created by the [`filter_map`] method on [`Iterator`]. See its @@ -1503,8 +1705,7 @@ impl Iterator for FilterMap #[inline] fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate + FilterMapImpl::size_hint(self) } #[inline] @@ -1567,10 +1768,46 @@ impl DoubleEndedIterator for FilterMap } } +// FilterMap specialization trait +// FIXME: #36262 +#[doc(hidden)] +trait FilterMapImpl { + fn size_hint(&self) -> (usize, Option); +} + +// General FilterMap impl +#[doc(hidden)] +impl FilterMapImpl for FilterMap + where P: FnMut(I::Item) -> Option +{ + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } +} + +// Specialized FilterMap impl for an underlying UnboundedIterator +#[doc(hidden)] +impl FilterMapImpl for FilterMap + where P: FnMut(I::Item) -> Option +{ + #[inline] + fn size_hint(&self) -> (usize, Option) { + // If the underlying iterator is unbounded, we will either filter out all items + // and thus diverge, or filter some of the infinitely many items out. + (usize::MAX, None) + } +} + #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for FilterMap where F: FnMut(I::Item) -> Option {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for FilterMap + where F: FnMut(I::Item) -> Option {} + /// An iterator that yields the current count and the element during iteration. /// /// This `struct` is created by the [`enumerate`] method on [`Iterator`]. See its @@ -1730,6 +1967,9 @@ unsafe impl TrustedLen for Enumerate where I: TrustedLen, {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Enumerate where I: UnboundedIterator {} + /// An iterator with a `peek()` that returns an optional reference to the next /// element. @@ -1845,6 +2085,9 @@ impl ExactSizeIterator for Peekable {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Peekable {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Peekable {} + impl Peekable { /// Returns a reference to the next() value without advancing the iterator. /// @@ -1945,8 +2188,7 @@ impl Iterator for SkipWhile #[inline] fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate + SkipWhileImpl::size_hint(self) } #[inline] @@ -1976,10 +2218,46 @@ impl Iterator for SkipWhile } } +// SkipWhile specialization trait +// FIXME: #36262 +#[doc(hidden)] +trait SkipWhileImpl { + fn size_hint(&self) -> (usize, Option); +} + +// General SkipWhile impl +#[doc(hidden)] +impl SkipWhileImpl for SkipWhile + where P: FnMut(&I::Item) -> bool +{ + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } +} + +// Specialized SkipWhile impl for underlying UnboundedIterator +#[doc(hidden)] +impl SkipWhileImpl for SkipWhile + where P: FnMut(&I::Item) -> bool +{ + #[inline] + fn size_hint(&self) -> (usize, Option) { + // If the underlying iterator is unbounded, we will either skip all items + // and thus diverge, or skip the first few of the infinitely many items. + (usize::MAX, None) + } +} + #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for SkipWhile where I: FusedIterator, P: FnMut(&I::Item) -> bool {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for SkipWhile + where I: UnboundedIterator, P: FnMut(&I::Item) -> bool {} + /// An iterator that only accepts elements while `predicate` is true. /// /// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its @@ -2127,12 +2405,7 @@ impl Iterator for Skip where I: Iterator { #[inline] fn size_hint(&self) -> (usize, Option) { - let (lower, upper) = self.iter.size_hint(); - - let lower = lower.saturating_sub(self.n); - let upper = upper.map(|x| x.saturating_sub(self.n)); - - (lower, upper) + SkipImpl::size_hint(self) } #[inline] @@ -2194,9 +2467,43 @@ impl DoubleEndedIterator for Skip where I: DoubleEndedIterator + ExactSize } } +// Skip specialization trait +// FIXME: #36262 +#[doc(hidden)] +trait SkipImpl { + fn size_hint(&self) -> (usize, Option); +} + +// General Skip impl +#[doc(hidden)] +impl SkipImpl for Skip { + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.iter.size_hint(); + + let lower = lower.saturating_sub(self.n); + let upper = upper.map(|x| x.saturating_sub(self.n)); + + (lower, upper) + } +} + +// Specialized Skip impl for an underlying UnboundedIterator +#[doc(hidden)] +impl SkipImpl for Skip { + #[inline] + fn size_hint(&self) -> (usize, Option) { + // We skip the first few of the infinitely many elements. + (usize::MAX, None) + } +} + #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Skip where I: FusedIterator {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Skip {} + /// An iterator that only iterates over the first `n` iterations of `iter`. /// /// This `struct` is created by the [`take`] method on [`Iterator`]. See its @@ -2278,6 +2585,9 @@ impl ExactSizeIterator for Take where I: ExactSizeIterator {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Take where I: FusedIterator {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl TrustedLen for Take {} + /// An iterator to maintain state while iterating another iterator. /// /// This `struct` is created by the [`scan`] method on [`Iterator`]. See its @@ -2391,13 +2701,7 @@ impl Iterator for FlatMap #[inline] fn size_hint(&self) -> (usize, Option) { - let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); - let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); - let lo = flo.saturating_add(blo); - match (self.iter.size_hint(), fhi, bhi) { - ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)), - _ => (lo, None) - } + FlatMapImpl::size_hint(self) } #[inline] @@ -2501,10 +2805,51 @@ impl DoubleEndedIterator for FlatMap wher } } +// FlatMap specialization trait +// FIXME: #36262 +#[doc(hidden)] +trait FlatMapImpl { + fn size_hint(&self) -> (usize, Option); +} + +// General FlatMap impl +impl FlatMapImpl for FlatMap + where F: FnMut(I::Item) -> U, +{ + #[inline] + default fn size_hint(&self) -> (usize, Option) { + let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); + let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), |it| it.size_hint()); + let lo = flo.saturating_add(blo); + match (self.iter.size_hint(), fhi, bhi) { + ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)), + _ => (lo, None) + } + } +} + +// Specialized FlatMap impl for an underlying UnboundedIterator +impl FlatMapImpl for FlatMap + where F: FnMut(I::Item) -> U, +{ + #[inline] + fn size_hint(&self) -> (usize, Option) { + // Either inner iterators return values, in which case there'll be infinitely many, + // or they don't return any, in which case we diverge. + (usize::MAX, None) + } +} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for FlatMap where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for FlatMap + where I: UnboundedIterator, + U: IntoIterator, + F: FnMut(I::Item) -> U, +{} + /// An iterator that yields `None` forever after the underlying iterator /// yields `None` once. /// @@ -2730,6 +3075,11 @@ impl ExactSizeIterator for Fuse where I: ExactSizeIterator { } } +// Actually it's useless to call `.fuse()` on an UnboundedIterator, as the `None` +// case will never occur. Anyway, this contract still holds. +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Fuse where I: UnboundedIterator {} + /// An iterator that calls a function with a reference to each element before /// yielding it. /// @@ -2841,3 +3191,7 @@ impl ExactSizeIterator for Inspect #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Inspect where F: FnMut(&I::Item) {} + +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Inspect + where F: FnMut(&I::Item) {} diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index e9aee4a4676de..3b12b4bf13877 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -13,7 +13,7 @@ use mem; use ops::{self, Add, Sub}; use usize; -use super::{FusedIterator, TrustedLen}; +use super::{FusedIterator, TrustedLen, UnboundedIterator}; /// Objects that can be stepped over in both directions. /// @@ -267,6 +267,12 @@ range_incl_exact_iter_impl!(u8 u16 i8 i16); range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64); range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64); +// We can safely implement `UnboundedIterator` for all RangeFrom because +// `Step::add_one` will always return `Self` or diverge, which is exactly +// what the contract `UnboundedIterator` describes. +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for ops::RangeFrom {} + #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for ops::Range { #[inline] diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index b405f35d5e4db..df0c407888c11 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -12,7 +12,7 @@ use fmt; use marker; use usize; -use super::{FusedIterator, TrustedLen}; +use super::{FusedIterator, TrustedLen, UnboundedIterator}; /// An iterator that repeats an element endlessly. /// @@ -44,6 +44,9 @@ impl DoubleEndedIterator for Repeat { #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Repeat {} +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl UnboundedIterator for Repeat {} + /// Creates a new iterator that endlessly repeats a single element. /// /// The `repeat()` function repeats a single value over and over and over and diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 11e668d228c48..afaf4879b9106 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -987,3 +987,34 @@ pub unsafe trait TrustedLen : Iterator {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, I: TrustedLen + ?Sized> TrustedLen for &'a mut I {} + +/// An iterator that will never return [`None`]. +/// +/// Any iterator implementing this trait will either continue to return +/// values infinitely, or diverge. +/// Additionally, its [`.size_hint`] must return `(usize::MAX, None)`. +/// +/// # Safety +/// +/// This trait must only be implemented when the contract is upheld. +/// +/// [`None`]: ../../std/option/enum.Option.html#variant.None +/// [`.size_hint`]: ../../std/iter/trait.Iterator.html#method.size_hint +// We can't implement FusedIterator for T where T: UnboundedIterator due to +// a clash for &'a mut I. Thus, we need to make it a supertrait. +#[unstable(feature = "unbounded_iter", issue = "0")] +pub unsafe trait UnboundedIterator : FusedIterator {} + +#[unstable(feature = "unbounded_iter", issue = "0")] +unsafe impl<'a, I: UnboundedIterator + ?Sized> UnboundedIterator for &'a mut I {} + +// Hacky auto trait to allow specialization of iter::Chain, +// because it requares either A: UI or B: UI or both. +// FIXME: #46813 +//#[unstable(feature = "unbounded_iter", issue = "0")] +//#[doc(hidden)] +//pub auto trait UnboundedIteratorAuto {} +// +//#[unstable(feature = "unbounded_iter", issue = "0")] +//impl !UnboundedIteratorAuto for (A, B) +// where A: UnboundedIteratorAuto, B: UnboundedIteratorAuto {} diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 5cac5b26d88bd..f9a0c7de8ea67 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -952,14 +952,14 @@ fn test_iterator_size_hint() { assert_eq!(c.clone().take(5).size_hint(), (5, Some(5))); assert_eq!(c.clone().skip(5).size_hint().1, None); assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None)); - assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None)); + assert_eq!(c.clone().skip_while(|_| false).size_hint(), (usize::MAX, None)); assert_eq!(c.clone().enumerate().size_hint(), (usize::MAX, None)); assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (usize::MAX, None)); assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10))); assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None)); - assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None)); + assert_eq!(c.clone().filter(|_| false).size_hint(), (usize::MAX, None)); assert_eq!(c.clone().map(|_| 0).size_hint(), (usize::MAX, None)); - assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None)); + assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (usize::MAX, None)); assert_eq!(vi.clone().take(5).size_hint(), (5, Some(5))); assert_eq!(vi.clone().take(12).size_hint(), (10, Some(10))); @@ -1701,3 +1701,117 @@ fn test_flat_map_try_folds() { assert_eq!(iter.try_rfold(0, i8::checked_add), None); assert_eq!(iter.next_back(), Some(35)); } + +fn test_unbounded_iterator(iter: I) { + assert_eq!(iter.size_hint(), (usize::MAX, None)) +} + +fn test_trusted_len(_: I) {} + +#[test] +fn test_unbounded_iterator_repeat() { + test_unbounded_iterator(repeat(0)) +} + +#[test] +fn test_unbounded_iterator_rangefrom() { + test_unbounded_iterator(0..) +} + +#[test] +fn test_unbounded_iterator_rev() { + test_unbounded_iterator(repeat(0).rev()) +} + +#[test] +fn test_unbounded_iterator_filter() { + test_unbounded_iterator(repeat(0).filter(|_| true)) +} + +#[test] +fn test_unbounded_iterator_cycle() { + test_unbounded_iterator(repeat(0).cycle()) +} + +#[test] +fn test_unbounded_iterator_fuse() { + test_unbounded_iterator(repeat(0).fuse()) +} + +#[test] +fn test_unbounded_iterator_map() { + test_unbounded_iterator(repeat(0).map(|_| 1)) +} + +#[test] +fn test_unbounded_iterator_inspect() { + test_unbounded_iterator(repeat(0).inspect(|_| {})) +} + +#[test] +fn test_unbounded_iterator_skip_while() { + test_unbounded_iterator(repeat(0).skip_while(|_| false)) +} + +#[test] +fn test_unbounded_iterator_filter_map() { + test_unbounded_iterator(repeat(0).filter_map(|_| Some(1))) +} + +#[test] +fn test_unbounded_iterator_zip() { + test_unbounded_iterator(repeat(0).zip(0..)) +} + +#[test] +fn test_unbounded_iterator_step_by() { + test_unbounded_iterator(repeat(0).step_by(5)) +} + +#[test] +fn test_unbounded_iterator_chain() { + test_unbounded_iterator(repeat(0).chain(0..)); + test_unbounded_iterator(repeat(0).chain(Some(1))); + // FIXME: #46813 +// test_unbounded_iterator(Some(1).into_iter().chain(repeat(0))); +} + +#[test] +fn test_unbounded_iterator_enumerate() { + test_unbounded_iterator(repeat(0).enumerate()) +} + +#[test] +fn test_unbounded_iterator_flat_map() { + test_unbounded_iterator(repeat(0).flat_map(|_| Some(1))); +} + +#[test] +fn test_unbounded_iterator_skip() { + test_unbounded_iterator(repeat(0).skip(5)) +} + +#[test] +fn test_unbounded_iterator_peekable() { + test_unbounded_iterator(repeat(0).peekable()) +} + +#[test] +fn test_unbounded_iterator_cloned() { + test_unbounded_iterator(repeat(&0).cloned()) +} + +#[test] +fn test_unbounded_iterator_box() { + test_unbounded_iterator(Box::new(repeat(0))) +} + +#[test] +fn test_trusted_len_repeat_take() { + test_trusted_len(repeat(0).take(100)) +} + +#[test] +fn test_trusted_len_rangefrom_take() { + test_trusted_len((0..).take(100)) +} diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 0e445cdac358a..281a96f0d04df 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -38,6 +38,7 @@ #![feature(step_trait)] #![feature(test)] #![feature(trusted_len)] +#![feature(unbounded_iter)] #![feature(try_from)] #![feature(try_trait)] #![feature(unique)]