@@ -3,7 +3,7 @@ use crate::iter::{
33 Cloned , Copied , Filter , FilterMap , Fuse , FusedIterator , InPlaceIterable , Map , TrustedFused ,
44 TrustedLen ,
55} ;
6- use crate :: iter:: { Once , OnceWith } ;
6+ use crate :: iter:: { Empty , Once , OnceWith } ;
77use crate :: num:: NonZero ;
88use crate :: ops:: { ControlFlow , Try } ;
99use crate :: result;
@@ -593,6 +593,7 @@ where
593593 }
594594}
595595
596+ // See also the `OneShot` specialization below.
596597impl < I , U > Iterator for FlattenCompat < I , U >
597598where
598599 I : Iterator < Item : IntoIterator < IntoIter = U , Item = U :: Item > > ,
@@ -601,7 +602,7 @@ where
601602 type Item = U :: Item ;
602603
603604 #[ inline]
604- fn next ( & mut self ) -> Option < U :: Item > {
605+ default fn next ( & mut self ) -> Option < U :: Item > {
605606 loop {
606607 if let elt @ Some ( _) = and_then_or_clear ( & mut self . frontiter , Iterator :: next) {
607608 return elt;
@@ -614,7 +615,7 @@ where
614615 }
615616
616617 #[ inline]
617- fn size_hint ( & self ) -> ( usize , Option < usize > ) {
618+ default fn size_hint ( & self ) -> ( usize , Option < usize > ) {
618619 let ( flo, fhi) = self . frontiter . as_ref ( ) . map_or ( ( 0 , Some ( 0 ) ) , U :: size_hint) ;
619620 let ( blo, bhi) = self . backiter . as_ref ( ) . map_or ( ( 0 , Some ( 0 ) ) , U :: size_hint) ;
620621 let lo = flo. saturating_add ( blo) ;
@@ -636,7 +637,7 @@ where
636637 }
637638
638639 #[ inline]
639- fn try_fold < Acc , Fold , R > ( & mut self , init : Acc , fold : Fold ) -> R
640+ default fn try_fold < Acc , Fold , R > ( & mut self , init : Acc , fold : Fold ) -> R
640641 where
641642 Self : Sized ,
642643 Fold : FnMut ( Acc , Self :: Item ) -> R ,
@@ -653,7 +654,7 @@ where
653654 }
654655
655656 #[ inline]
656- fn fold < Acc , Fold > ( self , init : Acc , fold : Fold ) -> Acc
657+ default fn fold < Acc , Fold > ( self , init : Acc , fold : Fold ) -> Acc
657658 where
658659 Fold : FnMut ( Acc , Self :: Item ) -> Acc ,
659660 {
@@ -669,7 +670,7 @@ where
669670
670671 #[ inline]
671672 #[ rustc_inherit_overflow_checks]
672- fn advance_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
673+ default fn advance_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
673674 #[ inline]
674675 #[ rustc_inherit_overflow_checks]
675676 fn advance < U : Iterator > ( n : usize , iter : & mut U ) -> ControlFlow < ( ) , usize > {
@@ -686,7 +687,7 @@ where
686687 }
687688
688689 #[ inline]
689- fn count ( self ) -> usize {
690+ default fn count ( self ) -> usize {
690691 #[ inline]
691692 #[ rustc_inherit_overflow_checks]
692693 fn count < U : Iterator > ( acc : usize , iter : U ) -> usize {
@@ -697,7 +698,7 @@ where
697698 }
698699
699700 #[ inline]
700- fn last ( self ) -> Option < Self :: Item > {
701+ default fn last ( self ) -> Option < Self :: Item > {
701702 #[ inline]
702703 fn last < U : Iterator > ( last : Option < U :: Item > , iter : U ) -> Option < U :: Item > {
703704 iter. last ( ) . or ( last)
@@ -707,13 +708,14 @@ where
707708 }
708709}
709710
711+ // See also the `OneShot` specialization below.
710712impl < I , U > DoubleEndedIterator for FlattenCompat < I , U >
711713where
712714 I : DoubleEndedIterator < Item : IntoIterator < IntoIter = U , Item = U :: Item > > ,
713715 U : DoubleEndedIterator ,
714716{
715717 #[ inline]
716- fn next_back ( & mut self ) -> Option < U :: Item > {
718+ default fn next_back ( & mut self ) -> Option < U :: Item > {
717719 loop {
718720 if let elt @ Some ( _) = and_then_or_clear ( & mut self . backiter , |b| b. next_back ( ) ) {
719721 return elt;
@@ -726,7 +728,7 @@ where
726728 }
727729
728730 #[ inline]
729- fn try_rfold < Acc , Fold , R > ( & mut self , init : Acc , fold : Fold ) -> R
731+ default fn try_rfold < Acc , Fold , R > ( & mut self , init : Acc , fold : Fold ) -> R
730732 where
731733 Self : Sized ,
732734 Fold : FnMut ( Acc , Self :: Item ) -> R ,
@@ -743,7 +745,7 @@ where
743745 }
744746
745747 #[ inline]
746- fn rfold < Acc , Fold > ( self , init : Acc , fold : Fold ) -> Acc
748+ default fn rfold < Acc , Fold > ( self , init : Acc , fold : Fold ) -> Acc
747749 where
748750 Fold : FnMut ( Acc , Self :: Item ) -> Acc ,
749751 {
@@ -759,7 +761,7 @@ where
759761
760762 #[ inline]
761763 #[ rustc_inherit_overflow_checks]
762- fn advance_back_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
764+ default fn advance_back_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
763765 #[ inline]
764766 #[ rustc_inherit_overflow_checks]
765767 fn advance < U : DoubleEndedIterator > ( n : usize , iter : & mut U ) -> ControlFlow < ( ) , usize > {
@@ -841,3 +843,198 @@ fn and_then_or_clear<T, U>(opt: &mut Option<T>, f: impl FnOnce(&mut T) -> Option
841843 }
842844 x
843845}
846+
847+ /// Specialization trait for iterator types that never return more than one item.
848+ ///
849+ /// Note that we still have to deal with the possibility that the iterator was
850+ /// already exhausted before it came into our control.
851+ #[ rustc_specialization_trait]
852+ trait OneShot { }
853+
854+ // These all have exactly one item, if not already consumed.
855+ impl < T > OneShot for Once < T > { }
856+ impl < F > OneShot for OnceWith < F > { }
857+ impl < T > OneShot for array:: IntoIter < T , 1 > { }
858+ impl < T > OneShot for option:: IntoIter < T > { }
859+ impl < T > OneShot for option:: Iter < ' _ , T > { }
860+ impl < T > OneShot for option:: IterMut < ' _ , T > { }
861+ impl < T > OneShot for result:: IntoIter < T > { }
862+ impl < T > OneShot for result:: Iter < ' _ , T > { }
863+ impl < T > OneShot for result:: IterMut < ' _ , T > { }
864+
865+ // These are always empty, which is fine to optimize too.
866+ impl < T > OneShot for Empty < T > { }
867+ impl < T > OneShot for array:: IntoIter < T , 0 > { }
868+
869+ // These adaptors never increase the number of items.
870+ // (There are more possible, but for now this matches BoundedSize above.)
871+ impl < I : OneShot > OneShot for Cloned < I > { }
872+ impl < I : OneShot > OneShot for Copied < I > { }
873+ impl < I : OneShot , P > OneShot for Filter < I , P > { }
874+ impl < I : OneShot , P > OneShot for FilterMap < I , P > { }
875+ impl < I : OneShot , F > OneShot for Map < I , F > { }
876+
877+ // Blanket impls pass this property through as well
878+ // (but we can't do `Box<I>` unless we expose this trait to alloc)
879+ impl < I : OneShot > OneShot for & mut I { }
880+
881+ #[ inline]
882+ fn into_item < I > ( inner : I ) -> Option < I :: Item >
883+ where
884+ I : IntoIterator < IntoIter : OneShot > ,
885+ {
886+ inner. into_iter ( ) . next ( )
887+ }
888+
889+ #[ inline]
890+ fn flatten_one < I : IntoIterator < IntoIter : OneShot > , Acc > (
891+ mut fold : impl FnMut ( Acc , I :: Item ) -> Acc ,
892+ ) -> impl FnMut ( Acc , I ) -> Acc {
893+ move |acc, inner| match inner. into_iter ( ) . next ( ) {
894+ Some ( item) => fold ( acc, item) ,
895+ None => acc,
896+ }
897+ }
898+
899+ #[ inline]
900+ fn try_flatten_one < I : IntoIterator < IntoIter : OneShot > , Acc , R : Try < Output = Acc > > (
901+ mut fold : impl FnMut ( Acc , I :: Item ) -> R ,
902+ ) -> impl FnMut ( Acc , I ) -> R {
903+ move |acc, inner| match inner. into_iter ( ) . next ( ) {
904+ Some ( item) => fold ( acc, item) ,
905+ None => try { acc } ,
906+ }
907+ }
908+
909+ #[ inline]
910+ fn advance_by_one < I > ( n : NonZero < usize > , inner : I ) -> Option < NonZero < usize > >
911+ where
912+ I : IntoIterator < IntoIter : OneShot > ,
913+ {
914+ match inner. into_iter ( ) . next ( ) {
915+ Some ( _) => NonZero :: new ( n. get ( ) - 1 ) ,
916+ None => Some ( n) ,
917+ }
918+ }
919+
920+ // Specialization: When the inner iterator `U` never returns more than one item, the `frontiter` and
921+ // `backiter` states are a waste, because they'll always have already consumed their item. So in
922+ // this impl, we completely ignore them and just focus on `self.iter`, and we only call the inner
923+ // `U::next()` one time.
924+ //
925+ // It's mostly fine if we accidentally mix this with the more generic impls, e.g. by forgetting to
926+ // specialize one of the methods. If the other impl did set the front or back, we wouldn't see it
927+ // here, but it would be empty anyway; and if the other impl looked for a front or back that we
928+ // didn't bother setting, it would just see `None` (or a previous empty) and move on.
929+ //
930+ // An exception to that is `advance_by(0)` and `advance_back_by(0)`, where the generic impls may set
931+ // `frontiter` or `backiter` without consuming the item, so we **must** override those.
932+ impl < I , U > Iterator for FlattenCompat < I , U >
933+ where
934+ I : Iterator < Item : IntoIterator < IntoIter = U , Item = U :: Item > > ,
935+ U : Iterator + OneShot ,
936+ {
937+ #[ inline]
938+ fn next ( & mut self ) -> Option < U :: Item > {
939+ while let Some ( inner) = self . iter . next ( ) {
940+ if let item @ Some ( _) = inner. into_iter ( ) . next ( ) {
941+ return item;
942+ }
943+ }
944+ None
945+ }
946+
947+ #[ inline]
948+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
949+ let ( lower, upper) = self . iter . size_hint ( ) ;
950+ match <I :: Item as ConstSizeIntoIterator >:: size ( ) {
951+ Some ( 0 ) => ( 0 , Some ( 0 ) ) ,
952+ Some ( 1 ) => ( lower, upper) ,
953+ _ => ( 0 , upper) ,
954+ }
955+ }
956+
957+ #[ inline]
958+ fn try_fold < Acc , Fold , R > ( & mut self , init : Acc , fold : Fold ) -> R
959+ where
960+ Self : Sized ,
961+ Fold : FnMut ( Acc , Self :: Item ) -> R ,
962+ R : Try < Output = Acc > ,
963+ {
964+ self . iter . try_fold ( init, try_flatten_one ( fold) )
965+ }
966+
967+ #[ inline]
968+ fn fold < Acc , Fold > ( self , init : Acc , fold : Fold ) -> Acc
969+ where
970+ Fold : FnMut ( Acc , Self :: Item ) -> Acc ,
971+ {
972+ self . iter . fold ( init, flatten_one ( fold) )
973+ }
974+
975+ #[ inline]
976+ fn advance_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
977+ if let Some ( n) = NonZero :: new ( n) {
978+ self . iter . try_fold ( n, advance_by_one) . map_or ( Ok ( ( ) ) , Err )
979+ } else {
980+ // Just advance the outer iterator
981+ self . iter . advance_by ( 0 )
982+ }
983+ }
984+
985+ #[ inline]
986+ fn count ( self ) -> usize {
987+ self . iter . filter_map ( into_item) . count ( )
988+ }
989+
990+ #[ inline]
991+ fn last ( self ) -> Option < Self :: Item > {
992+ self . iter . filter_map ( into_item) . last ( )
993+ }
994+ }
995+
996+ // Note: We don't actually care about `U: DoubleEndedIterator`, since forward and backward are the
997+ // same for a one-shot iterator, but we have to keep that to match the default specialization.
998+ impl < I , U > DoubleEndedIterator for FlattenCompat < I , U >
999+ where
1000+ I : DoubleEndedIterator < Item : IntoIterator < IntoIter = U , Item = U :: Item > > ,
1001+ U : DoubleEndedIterator + OneShot ,
1002+ {
1003+ #[ inline]
1004+ fn next_back ( & mut self ) -> Option < U :: Item > {
1005+ while let Some ( inner) = self . iter . next_back ( ) {
1006+ if let item @ Some ( _) = inner. into_iter ( ) . next ( ) {
1007+ return item;
1008+ }
1009+ }
1010+ None
1011+ }
1012+
1013+ #[ inline]
1014+ fn try_rfold < Acc , Fold , R > ( & mut self , init : Acc , fold : Fold ) -> R
1015+ where
1016+ Self : Sized ,
1017+ Fold : FnMut ( Acc , Self :: Item ) -> R ,
1018+ R : Try < Output = Acc > ,
1019+ {
1020+ self . iter . try_rfold ( init, try_flatten_one ( fold) )
1021+ }
1022+
1023+ #[ inline]
1024+ fn rfold < Acc , Fold > ( self , init : Acc , fold : Fold ) -> Acc
1025+ where
1026+ Fold : FnMut ( Acc , Self :: Item ) -> Acc ,
1027+ {
1028+ self . iter . rfold ( init, flatten_one ( fold) )
1029+ }
1030+
1031+ #[ inline]
1032+ fn advance_back_by ( & mut self , n : usize ) -> Result < ( ) , NonZero < usize > > {
1033+ if let Some ( n) = NonZero :: new ( n) {
1034+ self . iter . try_rfold ( n, advance_by_one) . map_or ( Ok ( ( ) ) , Err )
1035+ } else {
1036+ // Just advance the outer iterator
1037+ self . iter . advance_back_by ( 0 )
1038+ }
1039+ }
1040+ }
0 commit comments