@@ -797,8 +797,7 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
797
797
798
798
impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ty:: ExistentialPredicate < ' tcx > > {
799
799
fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
800
- let v = self . iter ( ) . map ( |p| p. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
801
- folder. tcx ( ) . intern_existential_predicates ( & v)
800
+ fold_list ( * self , folder, |tcx, v| tcx. intern_existential_predicates ( v) )
802
801
}
803
802
804
803
fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -808,8 +807,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
808
807
809
808
impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < Ty < ' tcx > > {
810
809
fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
811
- let v = self . iter ( ) . map ( |t| t. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
812
- folder. tcx ( ) . intern_type_list ( & v)
810
+ fold_list ( * self , folder, |tcx, v| tcx. intern_type_list ( v) )
813
811
}
814
812
815
813
fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -819,8 +817,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
819
817
820
818
impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ProjectionKind > {
821
819
fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
822
- let v = self . iter ( ) . map ( |t| t. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
823
- folder. tcx ( ) . intern_projs ( & v)
820
+ fold_list ( * self , folder, |tcx, v| tcx. intern_projs ( v) )
824
821
}
825
822
826
823
fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -984,17 +981,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
984
981
985
982
impl < ' tcx > TypeFoldable < ' tcx > for & ' tcx ty:: List < ty:: Predicate < ' tcx > > {
986
983
fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
987
- // This code is hot enough that it's worth specializing for a list of
988
- // length 0. (No other length is common enough to be worth singling
989
- // out).
990
- if self . len ( ) == 0 {
991
- self
992
- } else {
993
- // Don't bother interning if nothing changed, which is the common
994
- // case.
995
- let v = self . iter ( ) . map ( |p| p. fold_with ( folder) ) . collect :: < SmallVec < [ _ ; 8 ] > > ( ) ;
996
- if v[ ..] == self [ ..] { self } else { folder. tcx ( ) . intern_predicates ( & v) }
997
- }
984
+ fold_list ( * self , folder, |tcx, v| tcx. intern_predicates ( v) )
998
985
}
999
986
1000
987
fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
@@ -1067,3 +1054,34 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
1067
1054
false
1068
1055
}
1069
1056
}
1057
+
1058
+ // Does the equivalent of
1059
+ // ```
1060
+ // let v = self.iter().map(|p| p.fold_with(folder)).collect::<SmallVec<[_; 8]>>();
1061
+ // folder.tcx().intern_*(&v)
1062
+ // ```
1063
+ fn fold_list < ' tcx , F , T > (
1064
+ list : & ' tcx ty:: List < T > ,
1065
+ folder : & mut F ,
1066
+ intern : impl FnOnce ( TyCtxt < ' tcx > , & [ T ] ) -> & ' tcx ty:: List < T > ,
1067
+ ) -> & ' tcx ty:: List < T >
1068
+ where
1069
+ F : TypeFolder < ' tcx > ,
1070
+ T : TypeFoldable < ' tcx > + PartialEq + Copy ,
1071
+ {
1072
+ let mut iter = list. iter ( ) ;
1073
+ // Look for the first element that changed
1074
+ if let Some ( ( i, new_t) ) = iter. by_ref ( ) . enumerate ( ) . find_map ( |( i, t) | {
1075
+ let new_t = t. fold_with ( folder) ;
1076
+ if new_t == * t { None } else { Some ( ( i, new_t) ) }
1077
+ } ) {
1078
+ // An element changed, prepare to intern the resulting list
1079
+ let mut new_list = SmallVec :: < [ _ ; 8 ] > :: with_capacity ( list. len ( ) ) ;
1080
+ new_list. extend_from_slice ( & list[ ..i] ) ;
1081
+ new_list. push ( new_t) ;
1082
+ new_list. extend ( iter. map ( |t| t. fold_with ( folder) ) ) ;
1083
+ intern ( folder. tcx ( ) , & new_list)
1084
+ } else {
1085
+ list
1086
+ }
1087
+ }
0 commit comments