diff --git a/src/libcore/iter/adapters/fuse.rs b/src/libcore/iter/adapters/fuse.rs index a60ca64ec87c8..b69093f10cac6 100644 --- a/src/libcore/iter/adapters/fuse.rs +++ b/src/libcore/iter/adapters/fuse.rs @@ -1,9 +1,44 @@ +use crate::convert::Infallible; use crate::intrinsics; use crate::iter::{ DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedRandomAccess, }; use crate::ops::Try; +trait Stop: Sized { + /// Switch internal state of `Fuse` to indicate that underlying iterator returned `None` + fn stop(state: &mut Result); +} + +impl Stop for () { + fn stop(state: &mut Result) { + *state = Err(()) + } +} + +impl Stop for Infallible { + #[inline(always)] + fn stop(_state: &mut Result) { + // Intentionally does nothing: fused iterator returns `None`s after returning `None`, + // so there is no need to alter state + } +} + +trait StopState { + /// Type of value used to indicate that iterator returned `None` + type State: Stop + crate::fmt::Debug + Clone; +} + +impl StopState for I { + default type State = (); +} + +impl StopState for I { + type State = Infallible; +} + +type StopStateOf = ::State; + /// An iterator that yields `None` forever after the underlying iterator /// yields `None` once. /// @@ -16,12 +51,17 @@ use crate::ops::Try; #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] pub struct Fuse { - // NOTE: for `I: FusedIterator`, this is always assumed `Some`! - iter: Option, + iter: Result>, } + impl Fuse { pub(in crate::iter) fn new(iter: I) -> Fuse { - Fuse { iter: Some(iter) } + Fuse { iter: Ok(iter) } + } + + #[inline(always)] + fn stop(&mut self) { + StopStateOf::::stop(&mut self.iter); } } @@ -36,71 +76,71 @@ where type Item = ::Item; #[inline] - default fn next(&mut self) -> Option<::Item> { - let next = self.iter.as_mut()?.next(); + fn next(&mut self) -> Option<::Item> { + let next = self.iter.as_mut().ok()?.next(); if next.is_none() { - self.iter = None; + self.stop(); } next } #[inline] - default fn nth(&mut self, n: usize) -> Option { - let nth = self.iter.as_mut()?.nth(n); + fn nth(&mut self, n: usize) -> Option { + let nth = self.iter.as_mut().ok()?.nth(n); if nth.is_none() { - self.iter = None; + self.stop(); } nth } #[inline] - default fn last(self) -> Option { - self.iter?.last() + fn last(self) -> Option { + self.iter.ok()?.last() } #[inline] - default fn count(self) -> usize { + fn count(self) -> usize { self.iter.map_or(0, I::count) } #[inline] - default fn size_hint(&self) -> (usize, Option) { + fn size_hint(&self) -> (usize, Option) { self.iter.as_ref().map_or((0, Some(0)), I::size_hint) } #[inline] - default fn try_fold(&mut self, mut acc: Acc, fold: Fold) -> R + fn try_fold(&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 { + if let Ok(ref mut iter) = self.iter { acc = iter.try_fold(acc, fold)?; - self.iter = None; + self.stop(); } Try::from_ok(acc) } #[inline] - default fn fold(self, mut acc: Acc, fold: Fold) -> Acc + fn fold(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - if let Some(iter) = self.iter { + if let Ok(iter) = self.iter { acc = iter.fold(acc, fold); } acc } #[inline] - default fn find

(&mut self, predicate: P) -> Option + fn find

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { - let found = self.iter.as_mut()?.find(predicate); + let found = self.iter.as_mut().ok()?.find(predicate); if found.is_none() { - self.iter = None; + self.stop(); } found } @@ -112,56 +152,56 @@ where I: DoubleEndedIterator, { #[inline] - default fn next_back(&mut self) -> Option<::Item> { - let next = self.iter.as_mut()?.next_back(); + fn next_back(&mut self) -> Option<::Item> { + let next = self.iter.as_mut().ok()?.next_back(); if next.is_none() { - self.iter = None; + self.stop(); } next } #[inline] - default fn nth_back(&mut self, n: usize) -> Option<::Item> { - let nth = self.iter.as_mut()?.nth_back(n); + fn nth_back(&mut self, n: usize) -> Option<::Item> { + let nth = self.iter.as_mut().ok()?.nth_back(n); if nth.is_none() { - self.iter = None; + self.stop(); } nth } #[inline] - default fn try_rfold(&mut self, mut acc: Acc, fold: Fold) -> R + 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 { + if let Ok(ref mut iter) = self.iter { acc = iter.try_rfold(acc, fold)?; - self.iter = None; + self.stop(); } Try::from_ok(acc) } #[inline] - default fn rfold(self, mut acc: Acc, fold: Fold) -> Acc + fn rfold(self, mut acc: Acc, fold: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - if let Some(iter) = self.iter { + if let Ok(iter) = self.iter { acc = iter.rfold(acc, fold); } acc } #[inline] - default fn rfind

(&mut self, predicate: P) -> Option + fn rfind

(&mut self, predicate: P) -> Option where P: FnMut(&Self::Item) -> bool, { - let found = self.iter.as_mut()?.rfind(predicate); + let found = self.iter.as_mut().ok()?.rfind(predicate); if found.is_none() { - self.iter = None; + self.stop(); } found } @@ -171,156 +211,13 @@ where impl ExactSizeIterator for Fuse where I: ExactSizeIterator, -{ - default fn len(&self) -> usize { - self.iter.as_ref().map_or(0, I::len) - } - - default fn is_empty(&self) -> bool { - self.iter.as_ref().map_or(true, I::is_empty) - } -} - -// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some` -impl Fuse { - #[inline(always)] - fn as_inner(&self) -> &I { - match self.iter { - Some(ref iter) => iter, - // SAFETY: the specialized iterator never sets `None` - None => unsafe { intrinsics::unreachable() }, - } - } - - #[inline(always)] - fn as_inner_mut(&mut self) -> &mut I { - match self.iter { - Some(ref mut iter) => iter, - // SAFETY: the specialized iterator never sets `None` - None => unsafe { intrinsics::unreachable() }, - } - } - - #[inline(always)] - fn into_inner(self) -> I { - match self.iter { - Some(iter) => iter, - // SAFETY: the specialized iterator never sets `None` - None => unsafe { intrinsics::unreachable() }, - } - } -} - -#[stable(feature = "fused", since = "1.26.0")] -impl Iterator for Fuse -where - I: FusedIterator, -{ - #[inline] - fn next(&mut self) -> Option<::Item> { - self.as_inner_mut().next() - } - - #[inline] - fn nth(&mut self, n: usize) -> Option { - self.as_inner_mut().nth(n) - } - - #[inline] - fn last(self) -> Option { - self.into_inner().last() - } - - #[inline] - fn count(self) -> usize { - self.into_inner().count() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.as_inner().size_hint() - } - - #[inline] - fn try_fold(&mut self, init: Acc, fold: Fold) -> R - where - Self: Sized, - Fold: FnMut(Acc, Self::Item) -> R, - R: Try, - { - self.as_inner_mut().try_fold(init, fold) - } - - #[inline] - fn fold(self, init: Acc, fold: Fold) -> Acc - where - Fold: FnMut(Acc, Self::Item) -> Acc, - { - self.into_inner().fold(init, fold) - } - - #[inline] - fn find

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

(&mut self, predicate: P) -> Option - where - P: FnMut(&Self::Item) -> bool, - { - self.as_inner_mut().rfind(predicate) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for Fuse -where - I: ExactSizeIterator + FusedIterator, { fn len(&self) -> usize { - self.as_inner().len() + self.iter.as_ref().map_or(0, I::len) } fn is_empty(&self) -> bool { - self.as_inner().is_empty() + self.iter.as_ref().map_or(true, I::is_empty) } } @@ -330,9 +227,9 @@ where { unsafe fn get_unchecked(&mut self, i: usize) -> I::Item { match self.iter { - Some(ref mut iter) => iter.get_unchecked(i), + Ok(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(), + Err(_) => intrinsics::unreachable(), } }