From 758f4e715867573a4c56f6b92e96d6c4960bc2e8 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 7 Feb 2022 16:08:04 +0100 Subject: [PATCH] optimize `TypeFoldable` for 2 element tuples --- .../rustc_middle/src/ty/structural_impls.rs | 13 ------- 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 TypeFoldable<'tcx> for &'tcx ty::List> { - fn try_super_fold_with>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)) - } - - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List { fn try_super_fold_with>( 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> { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + // 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>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + /////////////////////////////////////////////////////////////////////////// // Public trait `Subst` //