@@ -805,8 +805,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
805
805
806
806
impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ty:: ExistentialPredicate < ' tcx > > {
807
807
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) )
810
809
}
811
810
812
811
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>>
816
815
817
816
impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < Ty < ' tcx > > {
818
817
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) )
821
819
}
822
820
823
821
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>> {
827
825
828
826
impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ProjectionKind > {
829
827
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) )
832
829
}
833
830
834
831
fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -992,17 +989,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
992
989
993
990
impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ty:: Predicate < ' tcx > > {
994
991
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) )
1006
993
}
1007
994
1008
995
fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -1075,3 +1062,34 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
1075
1062
false
1076
1063
}
1077
1064
}
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