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
This commit is contained in:
commit
d19458784f
1 changed files with 244 additions and 63 deletions
|
|
@ -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
|
||||
|
|
@ -51,6 +64,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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue