diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs index 3ebdf7b472796..6049428d54403 100644 --- a/library/core/src/iter/adapters/chain.rs +++ b/library/core/src/iter/adapters/chain.rs @@ -1,4 +1,4 @@ -use crate::iter::{FusedIterator, TrustedLen}; +use crate::iter::{FusedIterator, InfiniteIterator, TrustedLen}; use crate::num::NonZero; use crate::ops::Try; @@ -335,3 +335,15 @@ fn and_then_or_clear(opt: &mut Option, f: impl FnOnce(&mut T) -> Option } x } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Chain {} + +// FIXME: Get this working with the symmetrical variant +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for Chain +where + A: Iterator, + B: InfiniteIterator, +{ +} diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs index aea6d64281aec..3465d29f020f3 100644 --- a/library/core/src/iter/adapters/cloned.rs +++ b/library/core/src/iter/adapters/cloned.rs @@ -2,7 +2,9 @@ use core::num::NonZero; use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; -use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator}; +use crate::iter::{ + FusedIterator, InPlaceIterable, InfiniteIterator, TrustedLen, UncheckedIterator, +}; use crate::ops::Try; /// An iterator that clones the elements of an underlying iterator. @@ -188,3 +190,14 @@ unsafe impl InPlaceIterable for Cloned { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Cloned {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl<'a, I, T: 'a> InfiniteIterator for Cloned +where + I: InfiniteIterator, + T: Clone, +{ +} diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs index 23e4e25ab5388..410cc1ccb8f0f 100644 --- a/library/core/src/iter/adapters/copied.rs +++ b/library/core/src/iter/adapters/copied.rs @@ -1,6 +1,6 @@ use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; -use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen}; +use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedLen}; use crate::mem::{MaybeUninit, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::Try; @@ -273,3 +273,14 @@ unsafe impl InPlaceIterable for Copied { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Copied {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl<'a, I, T> InfiniteIterator for Copied +where + I: InfiniteIterator, + T: Copy + 'a, +{ +} diff --git a/library/core/src/iter/adapters/cycle.rs b/library/core/src/iter/adapters/cycle.rs index 6cb1a3a46763e..cc0c6fdc8529a 100644 --- a/library/core/src/iter/adapters/cycle.rs +++ b/library/core/src/iter/adapters/cycle.rs @@ -1,4 +1,4 @@ -use crate::iter::FusedIterator; +use crate::iter::{FusedIterator, InfiniteIterator}; use crate::num::NonZero; use crate::ops::Try; @@ -107,3 +107,9 @@ where #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Cycle where I: Clone + Iterator {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Cycle {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for Cycle {} diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index f7b9f0b7a5e9d..9dd6179b0f54c 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -1,6 +1,6 @@ use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; -use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen}; +use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused, TrustedLen}; use crate::num::NonZero; use crate::ops::Try; @@ -315,3 +315,9 @@ impl Default for Enumerate { Enumerate::new(Default::default()) } } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Enumerate {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for Enumerate {} diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs index dd08cd6f61c4c..d231d76fbc235 100644 --- a/library/core/src/iter/adapters/filter.rs +++ b/library/core/src/iter/adapters/filter.rs @@ -4,7 +4,7 @@ use core::ops::ControlFlow; use crate::fmt; use crate::iter::adapters::SourceIter; -use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused}; +use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused}; use crate::num::NonZero; use crate::ops::Try; @@ -214,3 +214,14 @@ unsafe impl InPlaceIterable for Filter { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Filter {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for Filter +where + I: InfiniteIterator, + P: FnMut(&I::Item) -> bool, +{ +} diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs index 24ec6b1741ce1..927f6dcbfbf45 100644 --- a/library/core/src/iter/adapters/filter_map.rs +++ b/library/core/src/iter/adapters/filter_map.rs @@ -1,5 +1,5 @@ use crate::iter::adapters::SourceIter; -use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused}; +use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused}; use crate::mem::{ManuallyDrop, MaybeUninit}; use crate::num::NonZero; use crate::ops::{ControlFlow, Try}; @@ -211,3 +211,12 @@ unsafe impl InPlaceIterable for FilterMap { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for FilterMap {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for FilterMap where + F: FnMut(I::Item) -> Option +{ +} diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index a820045521b9f..4a5972dddd18d 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -1,7 +1,7 @@ use crate::iter::adapters::SourceIter; use crate::iter::{ - Cloned, Copied, Empty, Filter, FilterMap, Fuse, FusedIterator, Map, Once, OnceWith, - TrustedFused, TrustedLen, + Cloned, Copied, Empty, Filter, FilterMap, Fuse, FusedIterator, InfiniteIterator, Map, Once, + OnceWith, TrustedFused, TrustedLen, }; use crate::num::NonZero; use crate::ops::{ControlFlow, Try}; @@ -172,6 +172,26 @@ where } } +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for FlatMap {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for FlatMap +where + I: ExactSizeIterator, + U: !ExactSizeIterator, +{ +} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for FlatMap +where + I: InfiniteIterator, + U: IntoIterator, + F: FnMut(I::Item) -> U, +{ +} + /// An iterator that flattens one level of nesting in an iterator of things /// that can be turned into iterators. /// @@ -349,6 +369,20 @@ where } } +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Flatten {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Flatten +where + I: ExactSizeIterator, + I::Item: !ExactSizeIterator, +{ +} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for Flatten where I: InfiniteIterator {} + /// Real logic of both `Flatten` and `FlatMap` which simply delegate to /// this type. #[derive(Clone, Debug)] @@ -712,6 +746,25 @@ where { } +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for FlattenCompat {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for FlattenCompat +where + I: ExactSizeIterator>, + U: Iterator + !ExactSizeIterator, +{ +} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for FlattenCompat +where + I: InfiniteIterator>, + U: Iterator, +{ +} + trait ConstSizeIntoIterator: IntoIterator { // FIXME(#31844): convert to an associated const once specialization supports that fn size() -> Option; diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs index 0e2a68a503e44..b109056cbf018 100644 --- a/library/core/src/iter/adapters/inspect.rs +++ b/library/core/src/iter/adapters/inspect.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::adapters::SourceIter; -use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused}; +use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused}; use crate::num::NonZero; use crate::ops::Try; @@ -172,3 +172,9 @@ unsafe impl InPlaceIterable for Inspect { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Inspect {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for Inspect where F: FnMut(&I::Item) {} diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index 007c2d5acc2d0..dbf80828edd36 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -1,6 +1,7 @@ use crate::fmt; use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; +use crate::iter::traits::InfiniteIterator; use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, UncheckedIterator}; use crate::num::NonZero; use crate::ops::Try; @@ -239,3 +240,14 @@ unsafe impl InPlaceIterable for Map { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Map {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for Map +where + F: FnMut(I::Item) -> B, + I: InfiniteIterator + !ExactSizeIterator, +{ +} diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs index c047c40de050e..4451700fe4145 100644 --- a/library/core/src/iter/adapters/map_while.rs +++ b/library/core/src/iter/adapters/map_while.rs @@ -88,3 +88,6 @@ unsafe impl InPlaceIterable for MapWhile { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for MapWhile {} diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index a55de75d56c6e..17c1589dd5084 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -1,5 +1,5 @@ use crate::iter::adapters::SourceIter; -use crate::iter::{FusedIterator, TrustedLen}; +use crate::iter::{FusedIterator, InfiniteIterator, TrustedLen}; use crate::ops::{ControlFlow, Try}; /// An iterator with a `peek()` that returns an optional reference to the next @@ -437,3 +437,9 @@ where unsafe { SourceIter::as_inner(&mut self.iter) } } } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Peekable {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for Peekable {} diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index 55c4a7f14fbd6..b7c50b41f074e 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -2,8 +2,8 @@ use crate::intrinsics::unlikely; use crate::iter::adapters::SourceIter; use crate::iter::adapters::zip::try_get_unchecked; use crate::iter::{ - FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, TrustedRandomAccess, - TrustedRandomAccessNoCoerce, + FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused, TrustedLen, + TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; use crate::num::NonZero; use crate::ops::{ControlFlow, Try}; @@ -287,3 +287,9 @@ where // I: TrustedLen would not. #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Skip where I: Iterator + TrustedRandomAccess {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Skip {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for Skip where I: InfiniteIterator {} diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs index 8ae453e76fa0d..7879c82d4ab31 100644 --- a/library/core/src/iter/adapters/skip_while.rs +++ b/library/core/src/iter/adapters/skip_while.rs @@ -1,6 +1,6 @@ use crate::fmt; use crate::iter::adapters::SourceIter; -use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused}; +use crate::iter::{FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused}; use crate::num::NonZero; use crate::ops::Try; @@ -128,3 +128,9 @@ unsafe impl InPlaceIterable for SkipWhile { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for SkipWhile {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for SkipWhile where P: FnMut(&I::Item) -> bool {} diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs index 2d0f210420317..16cc42b2255b1 100644 --- a/library/core/src/iter/adapters/step_by.rs +++ b/library/core/src/iter/adapters/step_by.rs @@ -1,5 +1,5 @@ use crate::intrinsics; -use crate::iter::{TrustedLen, TrustedRandomAccess, from_fn}; +use crate::iter::{InfiniteIterator, TrustedLen, TrustedRandomAccess, from_fn}; use crate::num::NonZero; use crate::ops::{Range, Try}; @@ -143,6 +143,12 @@ impl ExactSizeIterator for StepBy where I: ExactSizeIterator {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for StepBy where I: Iterator + TrustedRandomAccess {} +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for StepBy {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for StepBy {} + trait SpecRangeSetup { fn setup(inner: T, step: usize) -> T; } diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index b96335f415257..5e240e2d8fc94 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -1,6 +1,8 @@ use crate::cmp; use crate::iter::adapters::SourceIter; -use crate::iter::{FusedIterator, InPlaceIterable, TrustedFused, TrustedLen, TrustedRandomAccess}; +use crate::iter::{ + FusedIterator, InPlaceIterable, InfiniteIterator, TrustedFused, TrustedLen, TrustedRandomAccess, +}; use crate::num::NonZero; use crate::ops::{ControlFlow, Try}; @@ -361,15 +363,11 @@ impl DoubleEndedIterator for Take> { // because we have no way to return value of nth invocation of repeater followed // by n-1st without remembering all results. -#[stable(feature = "exact_size_take_repeat", since = "1.82.0")] -impl ExactSizeIterator for Take> { - fn len(&self) -> usize { - self.n - } -} - -#[stable(feature = "exact_size_take_repeat", since = "1.82.0")] -impl A, A> ExactSizeIterator for Take> { +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl ExactSizeIterator for Take +where + I: InfiniteIterator, +{ fn len(&self) -> usize { self.n } diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs index 06028ea98e7fd..e5f086cd3165b 100644 --- a/library/core/src/iter/adapters/take_while.rs +++ b/library/core/src/iter/adapters/take_while.rs @@ -129,3 +129,6 @@ unsafe impl InPlaceIterable for TakeWhile { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for TakeWhile {} diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index c5e199c30821d..a3707ef1d785f 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -1,5 +1,6 @@ use crate::cmp; use crate::fmt::{self, Debug}; +use crate::iter::traits::InfiniteIterator; use crate::iter::{ FusedIterator, InPlaceIterable, SourceIter, TrustedFused, TrustedLen, UncheckedIterator, }; @@ -413,6 +414,22 @@ where { } +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl ExactSizeIterator for Zip +where + A: ExactSizeIterator, + B: InfiniteIterator, +{ +} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl ExactSizeIterator for Zip +where + A: InfiniteIterator, + B: ExactSizeIterator, +{ +} + #[doc(hidden)] #[unstable(feature = "trusted_random_access", issue = "none")] unsafe impl TrustedRandomAccess for Zip diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index bc07324f5204c..b83f28817e299 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -450,6 +450,8 @@ pub use self::sources::{Successors, successors}; pub use self::traits::FusedIterator; #[unstable(issue = "none", feature = "inplace_iteration")] pub use self::traits::InPlaceIterable; +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +pub use self::traits::InfiniteIterator; #[stable(feature = "rust1", since = "1.0.0")] pub use self::traits::Iterator; #[unstable(issue = "none", feature = "trusted_fused")] diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index 9e43d5688cecc..d547e1c77e2bb 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -2,6 +2,7 @@ use super::{ FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep, }; use crate::ascii::Char as AsciiChar; +use crate::iter::InfiniteIterator; use crate::mem; use crate::net::{Ipv4Addr, Ipv6Addr}; use crate::num::NonZero; @@ -1031,6 +1032,12 @@ impl Iterator for ops::RangeFrom { } } +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for ops::RangeFrom {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for ops::RangeFrom {} + // Safety: See above implementation for `ops::Range` #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for ops::RangeFrom {} diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs index c4f5a483e5c2a..f0ec538749f2f 100644 --- a/library/core/src/iter/sources/repeat.rs +++ b/library/core/src/iter/sources/repeat.rs @@ -1,3 +1,4 @@ +use crate::iter::traits::InfiniteIterator; use crate::iter::{FusedIterator, TrustedLen}; use crate::num::NonZero; @@ -132,3 +133,9 @@ impl FusedIterator for Repeat {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Repeat {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for Repeat {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for Repeat {} diff --git a/library/core/src/iter/sources/repeat_with.rs b/library/core/src/iter/sources/repeat_with.rs index d3cd74a448375..651b49a7679e9 100644 --- a/library/core/src/iter/sources/repeat_with.rs +++ b/library/core/src/iter/sources/repeat_with.rs @@ -1,4 +1,5 @@ use crate::fmt; +use crate::iter::traits::InfiniteIterator; use crate::iter::{FusedIterator, TrustedLen}; use crate::ops::Try; @@ -120,3 +121,9 @@ impl A> FusedIterator for RepeatWith {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl A> TrustedLen for RepeatWith {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for RepeatWith {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl A> InfiniteIterator for RepeatWith {} diff --git a/library/core/src/iter/traits/infinite.rs b/library/core/src/iter/traits/infinite.rs new file mode 100644 index 0000000000000..00e2ced964378 --- /dev/null +++ b/library/core/src/iter/traits/infinite.rs @@ -0,0 +1,27 @@ +/// An iterator that will always produce more items. +/// +/// This is useful in order to have more types implement `ExactSizeIterator`. +/// +/// ``` +/// [1, 2, 3].zip(repeat(4)) +/// ``` +/// +/// This is an iterator with a known exact size of three. +/// +/// In order to propagate this information to the compiler, we +/// have: +/// +/// ```text +/// impl InfiniteIterator for Repeat {} +/// impl ExactSizeIterator for Zip, B> {} +/// impl ExactSizeIterator for Zip> {} +/// ``` +#[allow(multiple_supertrait_upcastable)] +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +pub trait InfiniteIterator: Iterator + !ExactSizeIterator {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl<'a, I: InfiniteIterator + ?Sized> InfiniteIterator for &'a mut I where + &'a mut I: !ExactSizeIterator +{ +} diff --git a/library/core/src/iter/traits/mod.rs b/library/core/src/iter/traits/mod.rs index b330e9ffe21ac..3c24bff63ee34 100644 --- a/library/core/src/iter/traits/mod.rs +++ b/library/core/src/iter/traits/mod.rs @@ -2,6 +2,7 @@ mod accum; mod collect; mod double_ended; mod exact_size; +mod infinite; mod iterator; mod marker; mod unchecked_iterator; @@ -19,6 +20,7 @@ pub use self::{ collect::{Extend, FromIterator, IntoIterator}, double_ended::DoubleEndedIterator, exact_size::ExactSizeIterator, + infinite::InfiniteIterator, iterator::Iterator, marker::{FusedIterator, TrustedLen}, }; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 86a68e18b0af4..c221f84f1b113 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -168,6 +168,7 @@ #![feature(min_specialization)] #![feature(multiple_supertrait_upcastable)] #![feature(must_not_suspend)] +#![feature(negative_bounds)] #![feature(negative_impls)] #![feature(never_type)] #![feature(no_core)] @@ -179,6 +180,7 @@ #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![feature(simd_ffi)] +#![feature(specialization)] #![feature(staged_api)] #![feature(stmt_expr_attributes)] #![feature(strict_provenance_lints)] diff --git a/library/core/src/range/iter.rs b/library/core/src/range/iter.rs index 24efd4a204a5f..859b9c60ba4f7 100644 --- a/library/core/src/range/iter.rs +++ b/library/core/src/range/iter.rs @@ -1,5 +1,6 @@ use crate::iter::{ - FusedIterator, Step, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep, + FusedIterator, InfiniteIterator, Step, TrustedLen, TrustedRandomAccess, + TrustedRandomAccessNoCoerce, TrustedStep, }; use crate::num::NonZero; use crate::range::{Range, RangeFrom, RangeInclusive, legacy}; @@ -337,3 +338,9 @@ impl IntoIterator for RangeFrom { IterRangeFrom(self.into()) } } + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl !ExactSizeIterator for IterRangeFrom {} + +#[stable(feature = "infinite_iterator_trait", since = "CURRENT_RUSTC_VERSION")] +impl InfiniteIterator for IterRangeFrom {} diff --git a/library/coretests/tests/iter/traits/exact_size.rs b/library/coretests/tests/iter/traits/exact_size.rs new file mode 100644 index 0000000000000..2309bf8da2f27 --- /dev/null +++ b/library/coretests/tests/iter/traits/exact_size.rs @@ -0,0 +1,94 @@ +use std::iter::{InfiniteIterator, once, repeat, repeat_with}; + +fn test_exact(iter: I, len: usize) { + assert_eq!(iter.len(), len); +} + +fn test_infinite(_: I) {} + +const N: u8 = 42; + +#[test] +fn test_exact_size_instance() { + // repeat(a) is infinite + test_infinite(repeat(1)); + + // RangeFrom is infinite + test_infinite(0..); + + // iter.cycle() is infinite + test_infinite(once(1).cycle()); + + // finite.chain(infinite) is infinite + test_infinite(once(1).chain(repeat(1))); + + // FIXME: Reenable, when we get the symmetrical case working + // // infinite.chain(finite) is infinite + // test_infinite(repeat(1).chain(once(2))); + + // infinite.chain(infinite) is infinite + test_infinite(repeat(2).chain(repeat(1))); + + // infinite.cloned() is infinite + test_infinite(repeat(&N).cloned()); + + // infinite.copied() is infinite + test_infinite(repeat(&N).copied()); + + // infinite.enumerate() is infinite + test_infinite((0..).enumerate()); + + // infinite.filter(p) is infinite + test_infinite((0..).filter(|a| a % 2 == 0)); + + // infinite.filter_map(f) is infinite + test_infinite((0..).filter_map(|a| Some(a % 2 == 0))); + + // infinite.filter_map(f) is infinite + test_infinite((0..).filter_map(|a| Some(a % 2 == 0))); + + // infinite.flatten() is infinite + test_infinite(repeat([1]).flatten()); + + // infinite.flat_map(f) is infinite + test_infinite((4..).flat_map(|_| [1, 2])); + + // infinite.inspect(f) is infinite + test_infinite((1..).inspect(|_| ())); + + // infinite.map(f) is infinite + test_infinite(repeat(1).map(|a| a)); + + // infinite.peekable() is infinite + test_infinite((0..).peekable()); + + // infinite.skip(n) is infinite + test_infinite((0..).skip(3)); + + // infinite.skip_while(p) is infinite + test_infinite((0..).skip_while(|n| *n < 10)); + + // infinite.step_by(n) is infinite + test_infinite((0..).step_by(10)); + + // repeat_with(f) is infinite + test_infinite(repeat_with(|| 1)); + + // infinite.take(n) is exact + let iter = repeat(1).take(0); + test_exact(iter, 0); + let iter = repeat(1).take(3); + test_exact(iter, 3); + + // infinite.zip(exact) is exact + let iter = repeat(1).zip(0..7); + test_exact(iter, 7); + let iter = repeat(1).zip(0..10); + test_exact(iter, 10); + + // exact.zip(infinite) is exact + let iter = (0..7).zip(repeat(1)); + test_exact(iter, 7); + let iter = (0..10).zip(repeat(1)); + test_exact(iter, 10); +} diff --git a/library/coretests/tests/iter/traits/mod.rs b/library/coretests/tests/iter/traits/mod.rs index 80619f53f25f9..cae2fa1c57f87 100644 --- a/library/coretests/tests/iter/traits/mod.rs +++ b/library/coretests/tests/iter/traits/mod.rs @@ -1,4 +1,5 @@ mod accum; mod double_ended; +mod exact_size; mod iterator; mod step;