@@ -805,8 +805,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
805805
806806impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ty:: ExistentialPredicate < ' tcx > > {
807807 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
808- let v = self . iter ( ) . map ( |p| p. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
809- folder. tcx ( ) . intern_existential_predicates ( & v)
808+ fold_list ( * self , folder, |tcx, v| tcx. intern_existential_predicates ( v) )
810809 }
811810
812811 fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -816,8 +815,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
816815
817816impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < Ty < ' tcx > > {
818817 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
819- let v = self . iter ( ) . map ( |t| t. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
820- folder. tcx ( ) . intern_type_list ( & v)
818+ fold_list ( * self , folder, |tcx, v| tcx. intern_type_list ( v) )
821819 }
822820
823821 fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -827,8 +825,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
827825
828826impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ProjectionKind > {
829827 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
830- let v = self . iter ( ) . map ( |t| t. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
831- folder. tcx ( ) . intern_projs ( & v)
828+ fold_list ( * self , folder, |tcx, v| tcx. intern_projs ( v) )
832829 }
833830
834831 fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -992,17 +989,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
992989
993990impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ty:: Predicate < ' tcx > > {
994991 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
995- // This code is hot enough that it's worth specializing for a list of
996- // length 0. (No other length is common enough to be worth singling
997- // out).
998- if self . len ( ) == 0 {
999- self
1000- } else {
1001- // Don't bother interning if nothing changed, which is the common
1002- // case.
1003- let v = self . iter ( ) . map ( |p| p. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
1004- if v[ ..] == self [ ..] { self } else { folder. tcx ( ) . intern_predicates ( & v) }
1005- }
992+ fold_list ( * self , folder, |tcx, v| tcx. intern_predicates ( v) )
1006993 }
1007994
1008995 fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -1075,3 +1062,34 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
10751062 false
10761063 }
10771064}
1065+
1066+ // Does the equivalent of
1067+ // ```
1068+ // let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
1069+ // folder.tcx().intern_*(&v)
1070+ // ```
1071+ fn fold_list < ' tcx , F , T > (
1072+ list : & ' tcx ty:: List < T > ,
1073+ folder : & mut F ,
1074+ intern : impl FnOnce ( TyCtxt < ' tcx > , & [ T ] ) -> & ' tcx ty:: List < T > ,
1075+ ) -> & ' tcx ty:: List < T >
1076+ where
1077+ F : TypeFolder < ' tcx > ,
1078+ T : TypeFoldable < ' tcx > + PartialEq + Copy ,
1079+ {
1080+ let mut iter = list. iter ( ) ;
1081+ // Look for the first element that changed
1082+ if let Some ( ( i, new_t) ) = iter. by_ref ( ) . enumerate ( ) . find_map ( |( i, t) | {
1083+ let new_t = t. fold_with ( folder) ;
1084+ if new_t == * t { None } else { Some ( ( i, new_t) ) }
1085+ } ) {
1086+ // An element changed, prepare to intern the resulting list
1087+ let mut new_list = SmallVec :: < [ _ ; 8 ] > :: with_capacity ( list. len ( ) ) ;
1088+ new_list. extend_from_slice ( & list[ ..i] ) ;
1089+ new_list. push ( new_t) ;
1090+ new_list. extend ( iter. map ( |t| t. fold_with ( folder) ) ) ;
1091+ intern ( folder. tcx ( ) , & new_list)
1092+ } else {
1093+ list
1094+ }
1095+ }
0 commit comments