From bff7b5130d49da7c86d688843292c10b82a4e6a0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 24 May 2022 09:22:24 +0200 Subject: [PATCH] move fast reject test out of `SelectionContext::match_impl`. `match_impl` has two call sites. For one of them (within `rematch_impl`) the fast reject test isn't necessary, because any rejection would represent a compiler bug. This commit moves the fast reject test to the other `match_impl` call site, in `assemble_candidates_from_impls`. This lets us move the fast reject test outside the `probe` call in that function. This avoids the taking of useless snapshots when the fast reject test succeeds, which gives a performance win when compiling the `bitmaps` and `nalgebra` crates. Co-authored-by: name --- .../src/traits/select/candidate_assembly.rs | 10 +++++++++- .../rustc_trait_selection/src/traits/select/mod.rs | 13 +++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 07720ba71ca..c8b4303e1e0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -539,8 +539,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), |impl_def_id| { + // Before we create the substitutions and everything, first + // consider a "quick reject". This avoids creating more types + // and so forth that we need to. + let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap(); + if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) { + return; + } + self.infcx.probe(|_| { - if let Ok(_substs) = self.match_impl(impl_def_id, obligation) { + if let Ok(_substs) = self.match_impl(impl_def_id, impl_trait_ref, obligation) { candidates.vec.push(ImplCandidate(impl_def_id)); } }); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 25b19c02a59..c7ebc194ea5 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2043,7 +2043,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { impl_def_id: DefId, obligation: &TraitObligation<'tcx>, ) -> Normalized<'tcx, SubstsRef<'tcx>> { - match self.match_impl(impl_def_id, obligation) { + let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap(); + match self.match_impl(impl_def_id, impl_trait_ref, obligation) { Ok(substs) => substs, Err(()) => { self.infcx.tcx.sess.delay_span_bug( @@ -2070,17 +2071,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_impl( &mut self, impl_def_id: DefId, + impl_trait_ref: EarlyBinder>, obligation: &TraitObligation<'tcx>, ) -> Result>, ()> { - let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap(); - - // Before we create the substitutions and everything, first - // consider a "quick reject". This avoids creating more types - // and so forth that we need to. - if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) { - return Err(()); - } - let placeholder_obligation = self.infcx().replace_bound_vars_with_placeholders(obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;