@@ -803,8 +803,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
803803
804804impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ty:: ExistentialPredicate < ' tcx > > {
805805 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
806- let v = self . iter ( ) . map ( |p| p. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
807- folder. tcx ( ) . intern_existential_predicates ( & v)
806+ fold_list ( * self , folder, |tcx, v| tcx. intern_existential_predicates ( v) )
808807 }
809808
810809 fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -814,8 +813,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
814813
815814impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < Ty < ' tcx > > {
816815 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
817- let v = self . iter ( ) . map ( |t| t. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
818- folder. tcx ( ) . intern_type_list ( & v)
816+ fold_list ( * self , folder, |tcx, v| tcx. intern_type_list ( v) )
819817 }
820818
821819 fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -825,8 +823,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
825823
826824impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ProjectionKind > {
827825 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
828- let v = self . iter ( ) . map ( |t| t. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
829- folder. tcx ( ) . intern_projs ( & v)
826+ fold_list ( * self , folder, |tcx, v| tcx. intern_projs ( v) )
830827 }
831828
832829 fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -990,17 +987,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
990987
991988impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ty:: Predicate < ' tcx > > {
992989 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
993- // This code is hot enough that it's worth specializing for a list of
994- // length 0. (No other length is common enough to be worth singling
995- // out).
996- if self . len ( ) == 0 {
997- self
998- } else {
999- // Don't bother interning if nothing changed, which is the common
1000- // case.
1001- let v = self . iter ( ) . map ( |p| p. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
1002- if v[ ..] == self [ ..] { self } else { folder. tcx ( ) . intern_predicates ( & v) }
1003- }
990+ fold_list ( * self , folder, |tcx, v| tcx. intern_predicates ( v) )
1004991 }
1005992
1006993 fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -1073,3 +1060,29 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
10731060 false
10741061 }
10751062}
1063+
1064+ fn fold_list < ' tcx , F , T > (
1065+ list : & ' tcx ty:: List < T > ,
1066+ folder : & mut F ,
1067+ intern : impl FnOnce ( TyCtxt < ' tcx > , & [ T ] ) -> & ' tcx ty:: List < T > ,
1068+ ) -> & ' tcx ty:: List < T >
1069+ where
1070+ F : TypeFolder < ' tcx > ,
1071+ T : TypeFoldable < ' tcx > + PartialEq + Copy ,
1072+ {
1073+ let mut iter = list. iter ( ) ;
1074+ // Look for the first element that changed
1075+ if let Some ( ( i, new_t) ) = iter. by_ref ( ) . enumerate ( ) . find_map ( |( i, t) | {
1076+ let new_t = t. fold_with ( folder) ;
1077+ if new_t == * t { None } else { Some ( ( i, new_t) ) }
1078+ } ) {
1079+ // An element changed, prepare to intern the resulting list
1080+ let mut new_list = SmallVec :: < [ _ ; 8 ] > :: with_capacity ( list. len ( ) ) ;
1081+ new_list. copy_from_slice ( & list[ ..i] ) ;
1082+ new_list. push ( new_t) ;
1083+ new_list. extend ( iter. map ( |t| t. fold_with ( folder) ) ) ;
1084+ intern ( folder. tcx ( ) , & new_list)
1085+ } else {
1086+ list
1087+ }
1088+ }
0 commit comments