Skip to content

Commit

Permalink
Add an early-exit to overlapping_impls
Browse files Browse the repository at this point in the history
This triggers in approx. 37% of all calls when building the stm32f0(x2)
crate, saving a small amount of time.
  • Loading branch information
jonas-schievink committed Feb 9, 2020
1 parent 07a34df commit d0bbdc3
Showing 1 changed file with 33 additions and 1 deletion.
34 changes: 33 additions & 1 deletion src/librustc/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ use crate::traits::SkipLeakCheck;
use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionContext};
use crate::ty::fold::TypeFoldable;
use crate::ty::subst::Subst;
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::{self, fast_reject, Ty, TyCtxt};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_span::symbol::sym;
use rustc_span::DUMMY_SP;
use std::iter;

/// Whether we do the orphan check relative to this crate or
/// to some remote crate.
Expand Down Expand Up @@ -70,6 +71,37 @@ where
impl1_def_id, impl2_def_id, intercrate_mode
);

// Before doing expensive operations like entering an inference context, do
// a quick check via fast_reject to tell if the impl headers could possibly
// unify.
let impl1_self = tcx.type_of(impl1_def_id);
let impl2_self = tcx.type_of(impl2_def_id);
let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
let impl2_ref = tcx.impl_trait_ref(impl2_def_id);

// Check if any of the input types definitely mismatch.
if impl1_ref
.iter()
.flat_map(|tref| tref.input_types())
.zip(impl2_ref.iter().flat_map(|tref| tref.input_types()))
.chain(iter::once((impl1_self, impl2_self)))
.any(|(ty1, ty2)| {
let ty1 = fast_reject::simplify_type(tcx, ty1, false);
let ty2 = fast_reject::simplify_type(tcx, ty2, false);
if let (Some(ty1), Some(ty2)) = (ty1, ty2) {
// Simplified successfully
ty1 != ty2
} else {
// Types might unify
false
}
})
{
// Some types involved are definitely different, so the impls couldn't possibly overlap.
debug!("overlapping_impls: fast_reject early-exit");
return no_overlap();
}

let overlaps = tcx.infer_ctxt().enter(|infcx| {
let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).is_some()
Expand Down

0 comments on commit d0bbdc3

Please sign in to comment.