@@ -402,14 +402,41 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
402402
403403impl < ' tcx > TypeFoldable < ' tcx > for SubstsRef < ' tcx > {
404404 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
405- let params: SmallVec < [ _ ; 8 ] > = self . iter ( ) . map ( |k| k. fold_with ( folder) ) . collect ( ) ;
406-
407- // If folding doesn't change the substs, it's faster to avoid
408- // calling `mk_substs` and instead reuse the existing substs.
409- if params[ ..] == self [ ..] {
410- self
411- } else {
412- folder. tcx ( ) . intern_substs ( & params)
405+ // This code is hot enough that it's worth specializing for the most
406+ // common length lists, to avoid the overhead of `SmallVec` creation.
407+ // The match arms are in order of frequency. The 1, 2, and 0 cases are
408+ // typically hit in 90--99.99% of cases. When folding doesn't change
409+ // the substs, it's faster to reuse the existing substs rather than
410+ // calling `intern_substs`.
411+ match self . len ( ) {
412+ 1 => {
413+ let param0 = self [ 0 ] . fold_with ( folder) ;
414+ if param0 == self [ 0 ] {
415+ self
416+ } else {
417+ folder. tcx ( ) . intern_substs ( & [ param0] )
418+ }
419+ }
420+ 2 => {
421+ let param0 = self [ 0 ] . fold_with ( folder) ;
422+ let param1 = self [ 1 ] . fold_with ( folder) ;
423+ if param0 == self [ 0 ] && param1 == self [ 1 ] {
424+ self
425+ } else {
426+ folder. tcx ( ) . intern_substs ( & [ param0, param1] )
427+ }
428+ }
429+ 0 => {
430+ self
431+ }
432+ _ => {
433+ let params: SmallVec < [ _ ; 8 ] > = self . iter ( ) . map ( |k| k. fold_with ( folder) ) . collect ( ) ;
434+ if params[ ..] == self [ ..] {
435+ self
436+ } else {
437+ folder. tcx ( ) . intern_substs ( & params)
438+ }
439+ }
413440 }
414441 }
415442
0 commit comments