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>
This commit is contained in:
parent
a76277c6c4
commit
bff7b5130d
@ -539,8 +539,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
obligation.predicate.def_id(),
|
obligation.predicate.def_id(),
|
||||||
obligation.predicate.skip_binder().trait_ref.self_ty(),
|
obligation.predicate.skip_binder().trait_ref.self_ty(),
|
||||||
|impl_def_id| {
|
|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(|_| {
|
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));
|
candidates.vec.push(ImplCandidate(impl_def_id));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2043,7 +2043,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
impl_def_id: DefId,
|
impl_def_id: DefId,
|
||||||
obligation: &TraitObligation<'tcx>,
|
obligation: &TraitObligation<'tcx>,
|
||||||
) -> Normalized<'tcx, SubstsRef<'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,
|
Ok(substs) => substs,
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
self.infcx.tcx.sess.delay_span_bug(
|
self.infcx.tcx.sess.delay_span_bug(
|
||||||
@ -2070,17 +2071,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
fn match_impl(
|
fn match_impl(
|
||||||
&mut self,
|
&mut self,
|
||||||
impl_def_id: DefId,
|
impl_def_id: DefId,
|
||||||
|
impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
|
||||||
obligation: &TraitObligation<'tcx>,
|
obligation: &TraitObligation<'tcx>,
|
||||||
) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
|
) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
|
||||||
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 =
|
let placeholder_obligation =
|
||||||
self.infcx().replace_bound_vars_with_placeholders(obligation.predicate);
|
self.infcx().replace_bound_vars_with_placeholders(obligation.predicate);
|
||||||
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
|
let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user