1
Fork 0

Try fast_reject::simplify_type in coherence before doing full check

Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
Co-authored-by: Ryan Levick <me@ryanlevick.com>
This commit is contained in:
Ryan Levick 2021-02-04 10:45:17 +01:00
parent d6a28a97e6
commit cdfc52fbd6

View file

@ -11,7 +11,7 @@ use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionCont
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, fast_reject, Ty, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::DUMMY_SP;
use std::iter;
@ -67,6 +67,36 @@ where
impl2_def_id={:?})",
impl1_def_id, impl2_def_id,
);
// 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.substs.types())
.zip(impl2_ref.iter().flat_map(|tref| tref.substs.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);