diff options
| author | Dylan DPC <dylan.dpc@gmail.com> | 2020-04-17 03:05:13 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-04-17 03:05:13 +0200 |
| commit | d19458784f3f25e53484f58f66aef8b973f002bc (patch) | |
| tree | cadc8be922554d6ba256c05534c979eb74006f43 | |
| parent | abd72f7fc2ced909ef21b9eb8029a392c4211c66 (diff) | |
| parent | abe5973b9d1202f1a6460c0116f22fc33c9506c5 (diff) | |
| download | rust-d19458784f3f25e53484f58f66aef8b973f002bc.tar.gz rust-d19458784f3f25e53484f58f66aef8b973f002bc.zip | |
Rollup merge of #70910 - rakshith-ravi:master, r=cuviper
Hides default fns inside Fuse impl to avoid exposing it to any crate Fixes #70796 @cuviper I've added some default, private traits to do the job for us. If required, I can expose them to a specific visibility if you want to call these functions for #70332 r? @cuviper
| -rw-r--r-- | src/libcore/iter/adapters/fuse.rs | 307 |
1 files changed, 244 insertions, 63 deletions
diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index 23bc215aa77..502fc2e6315 100644 --- a/src/libcore/iter/adapters/fuse.rs +++ b/src/libcore/iter/adapters/fuse.rs @@ -44,6 +44,19 @@ macro_rules! fuse { }; } +// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`. +// Implementing this as a directly-expanded macro helps codegen performance. +macro_rules! unchecked { + ($self:ident) => { + match $self { + Fuse { iter: Some(iter) } => iter, + // SAFETY: the specialized iterator never sets `None` + Fuse { iter: None } => unsafe { intrinsics::unreachable() }, + } + }; +} + +// Any implementation here is made internal to avoid exposing default fns outside this trait #[stable(feature = "rust1", since = "1.0.0")] impl<I> Iterator for Fuse<I> where @@ -52,6 +65,193 @@ where type Item = <I as Iterator>::Item; #[inline] + fn next(&mut self) -> Option<Self::Item> { + FuseImpl::next(self) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option<I::Item> { + FuseImpl::nth(self, n) + } + + #[inline] + fn last(self) -> Option<Self::Item> { + FuseImpl::last(self) + } + + #[inline] + fn count(self) -> usize { + FuseImpl::count(self) + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + FuseImpl::size_hint(self) + } + + #[inline] + fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try<Ok = Acc>, + { + FuseImpl::try_fold(self, acc, fold) + } + + #[inline] + fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + FuseImpl::fold(self, acc, fold) + } + + #[inline] + fn find<P>(&mut self, predicate: P) -> Option<Self::Item> + where + P: FnMut(&Self::Item) -> bool, + { + FuseImpl::find(self, predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<I> DoubleEndedIterator for Fuse<I> +where + I: DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<<I as Iterator>::Item> { + FuseImpl::next_back(self) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> { + FuseImpl::nth_back(self, n) + } + + #[inline] + fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try<Ok = Acc>, + { + FuseImpl::try_rfold(self, acc, fold) + } + + #[inline] + fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + FuseImpl::rfold(self, acc, fold) + } + + #[inline] + fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> + where + P: FnMut(&Self::Item) -> bool, + { + FuseImpl::rfind(self, predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<I> ExactSizeIterator for Fuse<I> +where + I: ExactSizeIterator, +{ + fn len(&self) -> usize { + FuseImpl::len(self) + } + + fn is_empty(&self) -> bool { + FuseImpl::is_empty(self) + } +} + +unsafe impl<I> TrustedRandomAccess for Fuse<I> +where + I: TrustedRandomAccess, +{ + unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { + match self.iter { + Some(ref mut iter) => iter.get_unchecked(i), + // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted. + None => intrinsics::unreachable(), + } + } + + fn may_have_side_effect() -> bool { + I::may_have_side_effect() + } +} + +// Fuse specialization trait +#[doc(hidden)] +trait FuseImpl<I> { + type Item; + + // Functions specific to any normal Iterators + fn next(&mut self) -> Option<Self::Item>; + fn nth(&mut self, n: usize) -> Option<Self::Item>; + fn last(self) -> Option<Self::Item>; + fn count(self) -> usize; + fn size_hint(&self) -> (usize, Option<usize>); + fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try<Ok = Acc>; + fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc; + fn find<P>(&mut self, predicate: P) -> Option<Self::Item> + where + P: FnMut(&Self::Item) -> bool; + + // Functions specific to DoubleEndedIterators + fn next_back(&mut self) -> Option<Self::Item> + where + I: DoubleEndedIterator; + fn nth_back(&mut self, n: usize) -> Option<Self::Item> + where + I: DoubleEndedIterator; + fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try<Ok = Acc>, + I: DoubleEndedIterator; + fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + I: DoubleEndedIterator; + fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> + where + P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator; + + // Functions specific to ExactSizeIterator + fn len(&self) -> usize + where + I: ExactSizeIterator; + fn is_empty(&self) -> bool + where + I: ExactSizeIterator; +} + +// General Fuse impl +#[doc(hidden)] +impl<I> FuseImpl<I> for Fuse<I> +where + I: Iterator, +{ + type Item = <I as Iterator>::Item; + + #[inline] default fn next(&mut self) -> Option<<I as Iterator>::Item> { fuse!(self.iter.next()) } @@ -117,20 +317,20 @@ where { fuse!(self.iter.find(predicate)) } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl<I> DoubleEndedIterator for Fuse<I> -where - I: DoubleEndedIterator, -{ #[inline] - default fn next_back(&mut self) -> Option<<I as Iterator>::Item> { + default fn next_back(&mut self) -> Option<<I as Iterator>::Item> + where + I: DoubleEndedIterator, + { fuse!(self.iter.next_back()) } #[inline] - default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> { + default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> + where + I: DoubleEndedIterator, + { fuse!(self.iter.nth_back(n)) } @@ -140,6 +340,7 @@ where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok = Acc>, + I: DoubleEndedIterator, { if let Some(ref mut iter) = self.iter { acc = iter.try_rfold(acc, fold)?; @@ -152,6 +353,7 @@ where default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, + I: DoubleEndedIterator, { if let Some(iter) = self.iter { acc = iter.rfold(acc, fold); @@ -163,24 +365,27 @@ where default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator, { fuse!(self.iter.rfind(predicate)) } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl<I> ExactSizeIterator for Fuse<I> -where - I: ExactSizeIterator, -{ - default fn len(&self) -> usize { + #[inline] + default fn len(&self) -> usize + where + I: ExactSizeIterator, + { match self.iter { Some(ref iter) => iter.len(), None => 0, } } - default fn is_empty(&self) -> bool { + #[inline] + default fn is_empty(&self) -> bool + where + I: ExactSizeIterator, + { match self.iter { Some(ref iter) => iter.is_empty(), None => true, @@ -188,20 +393,8 @@ where } } -// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`. -// Implementing this as a directly-expanded macro helps codegen performance. -macro_rules! unchecked { - ($self:ident) => { - match $self { - Fuse { iter: Some(iter) } => iter, - // SAFETY: the specialized iterator never sets `None` - Fuse { iter: None } => unsafe { intrinsics::unreachable() }, - } - }; -} - -#[stable(feature = "fused", since = "1.26.0")] -impl<I> Iterator for Fuse<I> +#[doc(hidden)] +impl<I> FuseImpl<I> for Fuse<I> where I: FusedIterator, { @@ -255,20 +448,20 @@ where { unchecked!(self).find(predicate) } -} -#[stable(feature = "fused", since = "1.26.0")] -impl<I> DoubleEndedIterator for Fuse<I> -where - I: DoubleEndedIterator + FusedIterator, -{ #[inline] - fn next_back(&mut self) -> Option<<I as Iterator>::Item> { + fn next_back(&mut self) -> Option<<I as Iterator>::Item> + where + I: DoubleEndedIterator, + { unchecked!(self).next_back() } #[inline] - fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> { + fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> + where + I: DoubleEndedIterator, + { unchecked!(self).nth_back(n) } @@ -278,6 +471,7 @@ where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok = Acc>, + I: DoubleEndedIterator, { unchecked!(self).try_rfold(init, fold) } @@ -286,6 +480,7 @@ where fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, + I: DoubleEndedIterator, { unchecked!(self).rfold(init, fold) } @@ -294,38 +489,24 @@ where fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item> where P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator, { unchecked!(self).rfind(predicate) } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl<I> ExactSizeIterator for Fuse<I> -where - I: ExactSizeIterator + FusedIterator, -{ - fn len(&self) -> usize { + #[inline] + fn len(&self) -> usize + where + I: ExactSizeIterator, + { unchecked!(self).len() } - fn is_empty(&self) -> bool { + #[inline] + fn is_empty(&self) -> bool + where + I: ExactSizeIterator, + { unchecked!(self).is_empty() } } - -unsafe impl<I> TrustedRandomAccess for Fuse<I> -where - I: TrustedRandomAccess, -{ - unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { - match self.iter { - Some(ref mut iter) => iter.get_unchecked(i), - // SAFETY: the caller asserts there is an item at `i`, so we're not exhausted. - None => intrinsics::unreachable(), - } - } - - fn may_have_side_effect() -> bool { - I::may_have_side_effect() - } -} |
