From 0a54a9403ddc41d13633c17a8d24c218dc563268 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Wed, 8 Apr 2020 05:39:00 +0530 Subject: [PATCH 1/3] Added FuseIteratorImpl, FustDoubleEndedIteratorImpl and FuseExactSizeIteratorImpl to avoid exposing default functions outside of the current crate. --- src/libcore/iter/adapters/fuse.rs | 379 ++++++++++++++++++++++-------- 1 file changed, 275 insertions(+), 104 deletions(-) diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index 23bc215aa779..946cd4753630 100644 --- a/src/libcore/iter/adapters/fuse.rs +++ b/src/libcore/iter/adapters/fuse.rs @@ -51,6 +51,182 @@ where { type Item = ::Item; + #[inline] + fn next(&mut self) -> Option { + FuseIteratorImpl::next(self) + } + + #[inline] + fn nth(&mut self, n: usize) -> Option { + FuseIteratorImpl::nth(self, n) + } + + #[inline] + fn last(self) -> Option { + FuseIteratorImpl::last(self) + } + + #[inline] + fn count(self) -> usize { + FuseIteratorImpl::count(self) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + FuseIteratorImpl::size_hint(self) + } + + #[inline] + fn try_fold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + FuseIteratorImpl::try_fold(self, acc, fold) + } + + #[inline] + fn fold(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + FuseIteratorImpl::fold(self, acc, fold) + } + + #[inline] + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + FuseIteratorImpl::find(self, predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for Fuse +where + I: DoubleEndedIterator, +{ + #[inline] + fn next_back(&mut self) -> Option<::Item> { + FuseDoubleEndedIteratorImpl::next_back(self) + } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option<::Item> { + FuseDoubleEndedIteratorImpl::nth_back(self, n) + } + + #[inline] + fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + FuseDoubleEndedIteratorImpl::try_rfold(self, acc, fold) + } + + #[inline] + fn rfold(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + FuseDoubleEndedIteratorImpl::rfold(self, acc, fold) + } + + #[inline] + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + FuseDoubleEndedIteratorImpl::rfind(self, predicate) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Fuse +where + I: ExactSizeIterator, +{ + fn len(&self) -> usize { + FuseExactSizeIteratorImpl::len(self) + } + + fn is_empty(&self) -> bool { + FuseExactSizeIteratorImpl::is_empty(self) + } +} + +// 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 Iterator for Fuse where I: FusedIterator {} + +#[stable(feature = "fused", since = "1.26.0")] +impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator + FusedIterator {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for Fuse where I: ExactSizeIterator + FusedIterator {} + +unsafe impl TrustedRandomAccess for Fuse +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 FuseIteratorImpl { + type Item; + fn next(&mut self) -> Option; + fn nth(&mut self, n: usize) -> Option; + fn last(self) -> Option; + fn count(self) -> usize; + fn size_hint(&self) -> (usize, Option); + fn try_fold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try; + fn fold(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc; + fn find

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool; +} + +// General Fuse impl +#[doc(hidden)] +impl FuseIteratorImpl for Fuse +where + I: Iterator, +{ + type Item = ::Item; + #[inline] default fn next(&mut self) -> Option<::Item> { fuse!(self.iter.next()) @@ -119,89 +295,8 @@ where } } -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for Fuse -where - I: DoubleEndedIterator, -{ - #[inline] - default fn next_back(&mut self) -> Option<::Item> { - fuse!(self.iter.next_back()) - } - - #[inline] - default fn nth_back(&mut self, n: usize) -> Option<::Item> { - fuse!(self.iter.nth_back(n)) - } - - #[inline] - default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> R, - R: Try, - { - if let Some(ref mut iter) = self.iter { - acc = iter.try_rfold(acc, fold)?; - self.iter = None; - } - Try::from_ok(acc) - } - - #[inline] - default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - if let Some(iter) = self.iter { - acc = iter.rfold(acc, fold); - } - acc - } - - #[inline] - default fn rfind

(&mut self, predicate: P) -> Option - where - P: FnMut(&Self::Item) -> bool, - { - fuse!(self.iter.rfind(predicate)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Fuse -where - I: ExactSizeIterator, -{ - default fn len(&self) -> usize { - match self.iter { - Some(ref iter) => iter.len(), - None => 0, - } - } - - default fn is_empty(&self) -> bool { - match self.iter { - Some(ref iter) => iter.is_empty(), - None => true, - } - } -} - -// 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 Iterator for Fuse +#[doc(hidden)] +impl FuseIteratorImpl for Fuse where I: FusedIterator, { @@ -257,8 +352,77 @@ where } } -#[stable(feature = "fused", since = "1.26.0")] -impl DoubleEndedIterator for Fuse +#[doc(hidden)] +trait FuseDoubleEndedIteratorImpl { + type Item; + fn next_back(&mut self) -> Option; + fn nth_back(&mut self, n: usize) -> Option; + fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try; + fn rfold(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc; + fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool; +} + +#[doc(hidden)] +impl FuseDoubleEndedIteratorImpl for Fuse +where + I: DoubleEndedIterator, +{ + type Item = ::Item; + + #[inline] + default fn next_back(&mut self) -> Option<::Item> { + fuse!(self.iter.next_back()) + } + + #[inline] + default fn nth_back(&mut self, n: usize) -> Option<::Item> { + fuse!(self.iter.nth_back(n)) + } + + #[inline] + default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + { + if let Some(ref mut iter) = self.iter { + acc = iter.try_rfold(acc, fold)?; + self.iter = None; + } + Try::from_ok(acc) + } + + #[inline] + default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(iter) = self.iter { + acc = iter.rfold(acc, fold); + } + acc + } + + #[inline] + default fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + { + fuse!(self.iter.rfind(predicate)) + } +} + +#[doc(hidden)] +impl FuseDoubleEndedIteratorImpl for Fuse where I: DoubleEndedIterator + FusedIterator, { @@ -299,8 +463,32 @@ where } } -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Fuse +#[doc(hidden)] +trait FuseExactSizeIteratorImpl { + fn len(&self) -> usize; + fn is_empty(&self) -> bool; +} + +impl FuseExactSizeIteratorImpl for Fuse +where + I: ExactSizeIterator, +{ + default fn len(&self) -> usize { + match self.iter { + Some(ref iter) => iter.len(), + None => 0, + } + } + + default fn is_empty(&self) -> bool { + match self.iter { + Some(ref iter) => iter.is_empty(), + None => true, + } + } +} + +impl FuseExactSizeIteratorImpl for Fuse where I: ExactSizeIterator + FusedIterator, { @@ -312,20 +500,3 @@ where unchecked!(self).is_empty() } } - -unsafe impl TrustedRandomAccess for Fuse -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() - } -} From 51cd29cf6cb4bd4ec025ae436f5d8ae6260335a2 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Fri, 10 Apr 2020 10:32:23 +0530 Subject: [PATCH 2/3] Added comments. Removed unnecessarry empty impls. Moved code to organise it better --- src/libcore/iter/adapters/fuse.rs | 37 +++++++++++++------------------ 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index 946cd4753630..c3968b101e50 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 Iterator for Fuse where @@ -159,27 +172,6 @@ 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 Iterator for Fuse where I: FusedIterator {} - -#[stable(feature = "fused", since = "1.26.0")] -impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator + FusedIterator {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Fuse where I: ExactSizeIterator + FusedIterator {} - unsafe impl TrustedRandomAccess for Fuse where I: TrustedRandomAccess, @@ -198,6 +190,9 @@ where } // Fuse specialization trait +// Iterators and DoubleEndedIterators cannot be overlapped successfully +// So, they're separated into each it's own trait to provide internal implementations +// Similarly, ExactSizeIterators cannot be overlapped, so requires its own trait #[doc(hidden)] trait FuseIteratorImpl { type Item; From abe5973b9d1202f1a6460c0116f22fc33c9506c5 Mon Sep 17 00:00:00 2001 From: Rakshith Ravi Date: Thu, 16 Apr 2020 01:19:51 +0530 Subject: [PATCH 3/3] Inlined everything into a single trait and trait impl --- src/libcore/iter/adapters/fuse.rs | 271 ++++++++++++++++-------------- 1 file changed, 143 insertions(+), 128 deletions(-) diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index c3968b101e50..502fc2e63150 100644 --- a/src/libcore/iter/adapters/fuse.rs +++ b/src/libcore/iter/adapters/fuse.rs @@ -66,27 +66,27 @@ where #[inline] fn next(&mut self) -> Option { - FuseIteratorImpl::next(self) + FuseImpl::next(self) } #[inline] fn nth(&mut self, n: usize) -> Option { - FuseIteratorImpl::nth(self, n) + FuseImpl::nth(self, n) } #[inline] fn last(self) -> Option { - FuseIteratorImpl::last(self) + FuseImpl::last(self) } #[inline] fn count(self) -> usize { - FuseIteratorImpl::count(self) + FuseImpl::count(self) } #[inline] fn size_hint(&self) -> (usize, Option) { - FuseIteratorImpl::size_hint(self) + FuseImpl::size_hint(self) } #[inline] @@ -96,7 +96,7 @@ where Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - FuseIteratorImpl::try_fold(self, acc, fold) + FuseImpl::try_fold(self, acc, fold) } #[inline] @@ -104,7 +104,7 @@ where where Fold: FnMut(Acc, Self::Item) -> Acc, { - FuseIteratorImpl::fold(self, acc, fold) + FuseImpl::fold(self, acc, fold) } #[inline] @@ -112,7 +112,7 @@ where where P: FnMut(&Self::Item) -> bool, { - FuseIteratorImpl::find(self, predicate) + FuseImpl::find(self, predicate) } } @@ -123,12 +123,12 @@ where { #[inline] fn next_back(&mut self) -> Option<::Item> { - FuseDoubleEndedIteratorImpl::next_back(self) + FuseImpl::next_back(self) } #[inline] fn nth_back(&mut self, n: usize) -> Option<::Item> { - FuseDoubleEndedIteratorImpl::nth_back(self, n) + FuseImpl::nth_back(self, n) } #[inline] @@ -138,7 +138,7 @@ where Fold: FnMut(Acc, Self::Item) -> R, R: Try, { - FuseDoubleEndedIteratorImpl::try_rfold(self, acc, fold) + FuseImpl::try_rfold(self, acc, fold) } #[inline] @@ -146,7 +146,7 @@ where where Fold: FnMut(Acc, Self::Item) -> Acc, { - FuseDoubleEndedIteratorImpl::rfold(self, acc, fold) + FuseImpl::rfold(self, acc, fold) } #[inline] @@ -154,7 +154,7 @@ where where P: FnMut(&Self::Item) -> bool, { - FuseDoubleEndedIteratorImpl::rfind(self, predicate) + FuseImpl::rfind(self, predicate) } } @@ -164,11 +164,11 @@ where I: ExactSizeIterator, { fn len(&self) -> usize { - FuseExactSizeIteratorImpl::len(self) + FuseImpl::len(self) } fn is_empty(&self) -> bool { - FuseExactSizeIteratorImpl::is_empty(self) + FuseImpl::is_empty(self) } } @@ -190,12 +190,11 @@ where } // Fuse specialization trait -// Iterators and DoubleEndedIterators cannot be overlapped successfully -// So, they're separated into each it's own trait to provide internal implementations -// Similarly, ExactSizeIterators cannot be overlapped, so requires its own trait #[doc(hidden)] -trait FuseIteratorImpl { +trait FuseImpl { type Item; + + // Functions specific to any normal Iterators fn next(&mut self) -> Option; fn nth(&mut self, n: usize) -> Option; fn last(self) -> Option; @@ -212,11 +211,41 @@ trait FuseIteratorImpl { fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool; + + // Functions specific to DoubleEndedIterators + fn next_back(&mut self) -> Option + where + I: DoubleEndedIterator; + fn nth_back(&mut self, n: usize) -> Option + where + I: DoubleEndedIterator; + fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + I: DoubleEndedIterator; + fn rfold(self, acc: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + I: DoubleEndedIterator; + fn rfind

(&mut self, predicate: P) -> Option + 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 FuseIteratorImpl for Fuse +impl FuseImpl for Fuse where I: Iterator, { @@ -288,10 +317,84 @@ where { fuse!(self.iter.find(predicate)) } + + #[inline] + default fn next_back(&mut self) -> Option<::Item> + where + I: DoubleEndedIterator, + { + fuse!(self.iter.next_back()) + } + + #[inline] + default fn nth_back(&mut self, n: usize) -> Option<::Item> + where + I: DoubleEndedIterator, + { + fuse!(self.iter.nth_back(n)) + } + + #[inline] + default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R + where + Self: Sized, + Fold: FnMut(Acc, Self::Item) -> R, + R: Try, + I: DoubleEndedIterator, + { + if let Some(ref mut iter) = self.iter { + acc = iter.try_rfold(acc, fold)?; + self.iter = None; + } + Try::from_ok(acc) + } + + #[inline] + default fn rfold(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); + } + acc + } + + #[inline] + default fn rfind

(&mut self, predicate: P) -> Option + where + P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator, + { + fuse!(self.iter.rfind(predicate)) + } + + #[inline] + default fn len(&self) -> usize + where + I: ExactSizeIterator, + { + match self.iter { + Some(ref iter) => iter.len(), + None => 0, + } + } + + #[inline] + default fn is_empty(&self) -> bool + where + I: ExactSizeIterator, + { + match self.iter { + Some(ref iter) => iter.is_empty(), + None => true, + } + } } #[doc(hidden)] -impl FuseIteratorImpl for Fuse +impl FuseImpl for Fuse where I: FusedIterator, { @@ -345,89 +448,20 @@ where { unchecked!(self).find(predicate) } -} - -#[doc(hidden)] -trait FuseDoubleEndedIteratorImpl { - type Item; - fn next_back(&mut self) -> Option; - fn nth_back(&mut self, n: usize) -> Option; - fn try_rfold(&mut self, acc: Acc, fold: Fold) -> R - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> R, - R: Try; - fn rfold(self, acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc; - fn rfind

(&mut self, predicate: P) -> Option - where - P: FnMut(&Self::Item) -> bool; -} - -#[doc(hidden)] -impl FuseDoubleEndedIteratorImpl for Fuse -where - I: DoubleEndedIterator, -{ - type Item = ::Item; #[inline] - default fn next_back(&mut self) -> Option<::Item> { - fuse!(self.iter.next_back()) - } - - #[inline] - default fn nth_back(&mut self, n: usize) -> Option<::Item> { - fuse!(self.iter.nth_back(n)) - } - - #[inline] - default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R + fn next_back(&mut self) -> Option<::Item> where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> R, - R: Try, + I: DoubleEndedIterator, { - if let Some(ref mut iter) = self.iter { - acc = iter.try_rfold(acc, fold)?; - self.iter = None; - } - Try::from_ok(acc) - } - - #[inline] - default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - if let Some(iter) = self.iter { - acc = iter.rfold(acc, fold); - } - acc - } - - #[inline] - default fn rfind

(&mut self, predicate: P) -> Option - where - P: FnMut(&Self::Item) -> bool, - { - fuse!(self.iter.rfind(predicate)) - } -} - -#[doc(hidden)] -impl FuseDoubleEndedIteratorImpl for Fuse -where - I: DoubleEndedIterator + FusedIterator, -{ - #[inline] - fn next_back(&mut self) -> Option<::Item> { unchecked!(self).next_back() } #[inline] - fn nth_back(&mut self, n: usize) -> Option<::Item> { + fn nth_back(&mut self, n: usize) -> Option<::Item> + where + I: DoubleEndedIterator, + { unchecked!(self).nth_back(n) } @@ -437,6 +471,7 @@ where Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try, + I: DoubleEndedIterator, { unchecked!(self).try_rfold(init, fold) } @@ -445,6 +480,7 @@ where fn rfold(self, init: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, + I: DoubleEndedIterator, { unchecked!(self).rfold(init, fold) } @@ -453,45 +489,24 @@ where fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, + I: DoubleEndedIterator, { unchecked!(self).rfind(predicate) } -} -#[doc(hidden)] -trait FuseExactSizeIteratorImpl { - fn len(&self) -> usize; - fn is_empty(&self) -> bool; -} - -impl FuseExactSizeIteratorImpl for Fuse -where - I: ExactSizeIterator, -{ - default fn len(&self) -> usize { - match self.iter { - Some(ref iter) => iter.len(), - None => 0, - } - } - - default fn is_empty(&self) -> bool { - match self.iter { - Some(ref iter) => iter.is_empty(), - None => true, - } - } -} - -impl FuseExactSizeIteratorImpl for Fuse -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() } }