diff options
| -rw-r--r-- | compiler/rustc_middle/src/ty/structural_impls.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/subst.rs | 39 |
2 files changed, 39 insertions, 13 deletions
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 8711216b042..42d7b141166 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -889,19 +889,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::Existentia } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> { - fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>( - self, - folder: &mut F, - ) -> Result<Self, F::Error> { - ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)) - } - - fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - self.iter().try_for_each(|t| t.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> { fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>( self, diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 7085168781c..59a560f7342 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -458,6 +458,45 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { } } +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> { + fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + // This code is fairly hot, though not as hot as `SubstsRef`. + // + // When compiling stage 2, I get the following results: + // + // len | total | % + // --- | --------- | ----- + // 2 | 15083590 | 48.1 + // 3 | 7540067 | 24.0 + // 1 | 5300377 | 16.9 + // 4 | 1351897 | 4.3 + // 0 | 1256849 | 4.0 + // + // I've tried it with some private repositories and got + // close to the same result, with 4 and 0 swapping places + // sometimes. + match self.len() { + 2 => { + let param0 = self[0].try_fold_with(folder)?; + let param1 = self[1].try_fold_with(folder)?; + if param0 == self[0] && param1 == self[1] { + Ok(self) + } else { + Ok(folder.tcx().intern_type_list(&[param0, param1])) + } + } + _ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)), + } + } + + fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + /////////////////////////////////////////////////////////////////////////// // Public trait `Subst` // |
