@@ -383,14 +383,41 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
383383
384384impl < ' tcx > TypeFoldable < ' tcx > for SubstsRef < ' tcx > {
385385 fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
386- let params: SmallVec < [ _ ; 8 ] > = self . iter ( ) . map ( |k| k. fold_with ( folder) ) . collect ( ) ;
387-
388- // If folding doesn't change the substs, it's faster to avoid
389- // calling `mk_substs` and instead reuse the existing substs.
390- if params[ ..] == self [ ..] {
391- self
392- } else {
393- folder. tcx ( ) . intern_substs ( & params)
386+ // This code is hot enough that it's worth specializing for the most
387+ // common length lists, to avoid the overhead of `SmallVec` creation.
388+ // The match arms are in order of frequency. The 1, 2, and 0 cases are
389+ // typically hit in 90--99.99% of cases. When folding doesn't change
390+ // the substs, it's faster to reuse the existing substs rather than
391+ // calling `intern_substs`.
392+ match self . len ( ) {
393+ 1 => {
394+ let param0 = self [ 0 ] . fold_with ( folder) ;
395+ if param0 == self [ 0 ] {
396+ self
397+ } else {
398+ folder. tcx ( ) . intern_substs ( & [ param0] )
399+ }
400+ }
401+ 2 => {
402+ let param0 = self [ 0 ] . fold_with ( folder) ;
403+ let param1 = self [ 1 ] . fold_with ( folder) ;
404+ if param0 == self [ 0 ] && param1 == self [ 1 ] {
405+ self
406+ } else {
407+ folder. tcx ( ) . intern_substs ( & [ param0, param1] )
408+ }
409+ }
410+ 0 => {
411+ self
412+ }
413+ _ => {
414+ let params: SmallVec < [ _ ; 8 ] > = self . iter ( ) . map ( |k| k. fold_with ( folder) ) . collect ( ) ;
415+ if params[ ..] == self [ ..] {
416+ self
417+ } else {
418+ folder. tcx ( ) . intern_substs ( & params)
419+ }
420+ }
394421 }
395422 }
396423
0 commit comments