Skip to content

Commit bff7b51

Browse files
lcnrnnethercote
andcommitted
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 <n.nethercote@gmail.com>
1 parent a76277c commit bff7b51

File tree

2 files changed

+12
-11
lines changed

2 files changed

+12
-11
lines changed

Diff for: compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -539,8 +539,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
539539
obligation.predicate.def_id(),
540540
obligation.predicate.skip_binder().trait_ref.self_ty(),
541541
|impl_def_id| {
542+
// Before we create the substitutions and everything, first
543+
// consider a "quick reject". This avoids creating more types
544+
// and so forth that we need to.
545+
let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
546+
if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) {
547+
return;
548+
}
549+
542550
self.infcx.probe(|_| {
543-
if let Ok(_substs) = self.match_impl(impl_def_id, obligation) {
551+
if let Ok(_substs) = self.match_impl(impl_def_id, impl_trait_ref, obligation) {
544552
candidates.vec.push(ImplCandidate(impl_def_id));
545553
}
546554
});

Diff for: compiler/rustc_trait_selection/src/traits/select/mod.rs

+3-10
Original file line numberDiff line numberDiff line change
@@ -2043,7 +2043,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20432043
impl_def_id: DefId,
20442044
obligation: &TraitObligation<'tcx>,
20452045
) -> Normalized<'tcx, SubstsRef<'tcx>> {
2046-
match self.match_impl(impl_def_id, obligation) {
2046+
let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
2047+
match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
20472048
Ok(substs) => substs,
20482049
Err(()) => {
20492050
self.infcx.tcx.sess.delay_span_bug(
@@ -2070,17 +2071,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
20702071
fn match_impl(
20712072
&mut self,
20722073
impl_def_id: DefId,
2074+
impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
20732075
obligation: &TraitObligation<'tcx>,
20742076
) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
2075-
let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
2076-
2077-
// Before we create the substitutions and everything, first
2078-
// consider a "quick reject". This avoids creating more types
2079-
// and so forth that we need to.
2080-
if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) {
2081-
return Err(());
2082-
}
2083-
20842077
let placeholder_obligation =
20852078
self.infcx().replace_bound_vars_with_placeholders(obligation.predicate);
20862079
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;

0 commit comments

Comments
 (0)