Skip to content

Commit 722ad22

Browse files
committed
Add InfiniteIterator trait
This enables more ExactSizeIterator instances, specifically, those for `Take`, where the sub-iterator is infinite, and `Zip` where the one sub-iterator is infinite, and the other is exact sized. Previously, in #146642, I sought to add specific instances for `Zip<Repeat<A>, I>` and its symmatrical mirror. Introducing `InfiniteIterator` provides much broader support for `ExactSizeIterator`. For example, ```rust [1, 2, 3].into_iter().chain(repeat(1)).take(5) ``` Will now happily resolve to an instance of `ExactSizeIterator`. The downside of this approach is that, to avoid the overlapping instance with `Zip`, I had to introduce a negative trait bound, which, IIUC, isn't available outside of the compiler. If anyone knows of a better way to handle the overlapping instances, or a way I can expose something which triggers the negative instance, that would be very helpful. There's also a missing symmetrical instance for `Chain`. Solutions are welcome.
1 parent 8a1b399 commit 722ad22

28 files changed

+366
-26
lines changed

library/core/src/iter/adapters/chain.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::iter::{FusedIterator, TrustedLen};
1+
use crate::iter::{FusedIterator, InfiniteIterator, TrustedLen};
22
use crate::num::NonZero;
33
use crate::ops::Try;
44

@@ -335,3 +335,15 @@ fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option
335335
}
336336
x
337337
}
338+
339+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
340+
impl<A, B> !ExactSizeIterator for Chain<A, B> {}
341+
342+
// FIXME: Get this working with the symmetrical variant
343+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
344+
impl<A, B> InfiniteIterator for Chain<A, B>
345+
where
346+
A: Iterator,
347+
B: InfiniteIterator<Item = A::Item>,
348+
{
349+
}

library/core/src/iter/adapters/cloned.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use core::num::NonZero;
22

33
use crate::iter::adapters::zip::try_get_unchecked;
44
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
5-
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator};
5+
use crate::iter::{
6+
FusedIterator, InPlaceIterable, InfiniteIterator, TrustedLen, UncheckedIterator,
7+
};
68
use crate::ops::Try;
79

810
/// An iterator that clones the elements of an underlying iterator.
@@ -188,3 +190,14 @@ unsafe impl<I: InPlaceIterable> InPlaceIterable for Cloned<I> {
188190
const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
189191
const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
190192
}
193+
194+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
195+
impl<I: !ExactSizeIterator> !ExactSizeIterator for Cloned<I> {}
196+
197+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
198+
impl<'a, I, T: 'a> InfiniteIterator for Cloned<I>
199+
where
200+
I: InfiniteIterator<Item = &'a T>,
201+
T: Clone,
202+
{
203+
}

library/core/src/iter/adapters/copied.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::iter::adapters::zip::try_get_unchecked;
22
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
3-
use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
3+
use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedLen};
44
use crate::mem::{MaybeUninit, SizedTypeProperties};
55
use crate::num::NonZero;
66
use crate::ops::Try;
@@ -273,3 +273,14 @@ unsafe impl<I: InPlaceIterable> InPlaceIterable for Copied<I> {
273273
const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
274274
const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
275275
}
276+
277+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
278+
impl<I: !ExactSizeIterator> !ExactSizeIterator for Copied<I> {}
279+
280+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
281+
impl<'a, I, T> InfiniteIterator for Copied<I>
282+
where
283+
I: InfiniteIterator<Item = &'a T>,
284+
T: Copy + 'a,
285+
{
286+
}

library/core/src/iter/adapters/cycle.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::iter::FusedIterator;
1+
use crate::iter::{FusedIterator, InfiniteIterator};
22
use crate::num::NonZero;
33
use crate::ops::Try;
44

@@ -107,3 +107,9 @@ where
107107

108108
#[stable(feature = "fused", since = "1.26.0")]
109109
impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
110+
111+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
112+
impl<I> !ExactSizeIterator for Cycle<I> {}
113+
114+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
115+
impl<I: Clone + Iterator> InfiniteIterator for Cycle<I> {}

library/core/src/iter/adapters/enumerate.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::iter::adapters::zip::try_get_unchecked;
22
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
3-
use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen};
3+
use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused, TrustedLen};
44
use crate::num::NonZero;
55
use crate::ops::Try;
66

@@ -315,3 +315,9 @@ impl<I: Default> Default for Enumerate<I> {
315315
Enumerate::new(Default::default())
316316
}
317317
}
318+
319+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
320+
impl<I: !ExactSizeIterator> !ExactSizeIterator for Enumerate<I> {}
321+
322+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
323+
impl<I: InfiniteIterator> InfiniteIterator for Enumerate<I> {}

library/core/src/iter/adapters/filter.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use core::ops::ControlFlow;
44

55
use crate::fmt;
66
use crate::iter::adapters::SourceIter;
7-
use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
7+
use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused};
88
use crate::num::NonZero;
99
use crate::ops::Try;
1010

@@ -214,3 +214,14 @@ unsafe impl<I: InPlaceIterable, P> InPlaceIterable for Filter<I, P> {
214214
const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
215215
const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
216216
}
217+
218+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
219+
impl<I, P> !ExactSizeIterator for Filter<I, P> {}
220+
221+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
222+
impl<I, P> InfiniteIterator for Filter<I, P>
223+
where
224+
I: InfiniteIterator,
225+
P: FnMut(&I::Item) -> bool,
226+
{
227+
}

library/core/src/iter/adapters/filter_map.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::iter::adapters::SourceIter;
2-
use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
2+
use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused};
33
use crate::mem::{ManuallyDrop, MaybeUninit};
44
use crate::num::NonZero;
55
use crate::ops::{ControlFlow, Try};
@@ -211,3 +211,12 @@ unsafe impl<I: InPlaceIterable, F> InPlaceIterable for FilterMap<I, F> {
211211
const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
212212
const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
213213
}
214+
215+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
216+
impl<I, F> !ExactSizeIterator for FilterMap<I, F> {}
217+
218+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
219+
impl<B, I: InfiniteIterator, F> InfiniteIterator for FilterMap<I, F> where
220+
F: FnMut(I::Item) -> Option<B>
221+
{
222+
}

library/core/src/iter/adapters/flatten.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::iter::adapters::SourceIter;
22
use crate::iter::{
3-
Cloned, Copied, Empty, Filter, FilterMap, Fuse, FusedIterator, Map, Once, OnceWith,
4-
TrustedFused, TrustedLen,
3+
Cloned, Copied, Empty, Filter, FilterMap, Fuse, FusedIterator, InfiniteIterator, Map, Once,
4+
OnceWith, TrustedFused, TrustedLen,
55
};
66
use crate::num::NonZero;
77
use crate::ops::{ControlFlow, Try};
@@ -172,6 +172,26 @@ where
172172
}
173173
}
174174

175+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
176+
impl<I: !ExactSizeIterator, U, F> !ExactSizeIterator for FlatMap<I, U, F> {}
177+
178+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
179+
impl<I, U, F> !ExactSizeIterator for FlatMap<I, U, F>
180+
where
181+
I: ExactSizeIterator<Item = U>,
182+
U: !ExactSizeIterator,
183+
{
184+
}
185+
186+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
187+
impl<I, U, F> InfiniteIterator for FlatMap<I, U, F>
188+
where
189+
I: InfiniteIterator,
190+
U: IntoIterator,
191+
F: FnMut(I::Item) -> U,
192+
{
193+
}
194+
175195
/// An iterator that flattens one level of nesting in an iterator of things
176196
/// that can be turned into iterators.
177197
///
@@ -349,6 +369,20 @@ where
349369
}
350370
}
351371

372+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
373+
impl<I: !ExactSizeIterator> !ExactSizeIterator for Flatten<I> {}
374+
375+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
376+
impl<I> !ExactSizeIterator for Flatten<I>
377+
where
378+
I: ExactSizeIterator,
379+
I::Item: !ExactSizeIterator,
380+
{
381+
}
382+
383+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
384+
impl<I> InfiniteIterator for Flatten<I> where I: InfiniteIterator<Item: IntoIterator> {}
385+
352386
/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
353387
/// this type.
354388
#[derive(Clone, Debug)]
@@ -712,6 +746,25 @@ where
712746
{
713747
}
714748

749+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
750+
impl<I: !ExactSizeIterator, U> !ExactSizeIterator for FlattenCompat<I, U> {}
751+
752+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
753+
impl<I, U> !ExactSizeIterator for FlattenCompat<I, U>
754+
where
755+
I: ExactSizeIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
756+
U: Iterator + !ExactSizeIterator,
757+
{
758+
}
759+
760+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
761+
impl<I, U> InfiniteIterator for FlattenCompat<I, U>
762+
where
763+
I: InfiniteIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
764+
U: Iterator,
765+
{
766+
}
767+
715768
trait ConstSizeIntoIterator: IntoIterator {
716769
// FIXME(#31844): convert to an associated const once specialization supports that
717770
fn size() -> Option<usize>;

library/core/src/iter/adapters/inspect.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::fmt;
22
use crate::iter::adapters::SourceIter;
3-
use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused};
3+
use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused};
44
use crate::num::NonZero;
55
use crate::ops::Try;
66

@@ -172,3 +172,9 @@ unsafe impl<I: InPlaceIterable, F> InPlaceIterable for Inspect<I, F> {
172172
const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
173173
const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
174174
}
175+
176+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
177+
impl<I: !ExactSizeIterator, F> !ExactSizeIterator for Inspect<I, F> {}
178+
179+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
180+
impl<I: InfiniteIterator, F> InfiniteIterator for Inspect<I, F> where F: FnMut(&I::Item) {}

library/core/src/iter/adapters/map.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::fmt;
22
use crate::iter::adapters::zip::try_get_unchecked;
33
use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
4+
use crate::iter::traits::InfiniteIterator;
45
use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, UncheckedIterator};
56
use crate::num::NonZero;
67
use crate::ops::Try;
@@ -239,3 +240,14 @@ unsafe impl<I: InPlaceIterable, F> InPlaceIterable for Map<I, F> {
239240
const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
240241
const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
241242
}
243+
244+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
245+
impl<I: !ExactSizeIterator, F> !ExactSizeIterator for Map<I, F> {}
246+
247+
#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")]
248+
impl<B, I: Iterator, F> InfiniteIterator for Map<I, F>
249+
where
250+
F: FnMut(I::Item) -> B,
251+
I: InfiniteIterator + !ExactSizeIterator,
252+
{
253+
}

0 commit comments

Comments
 (0)