@@ -11,7 +11,7 @@ use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionCont
11
11
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
12
12
use rustc_middle::ty::fold::TypeFoldable;
13
13
use rustc_middle::ty::subst::Subst;
14
- use rustc_middle::ty::{self, Ty, TyCtxt};
14
+ use rustc_middle::ty::{self, fast_reject, Ty, TyCtxt};
15
15
use rustc_span::symbol::sym;
16
16
use rustc_span::DUMMY_SP;
17
17
use std::iter;
67
67
impl2_def_id={:?})",
68
68
impl1_def_id, impl2_def_id,
69
69
);
70
+ // Before doing expensive operations like entering an inference context, do
71
+ // a quick check via fast_reject to tell if the impl headers could possibly
72
+ // unify.
73
+ let impl1_self = tcx.type_of(impl1_def_id);
74
+ let impl2_self = tcx.type_of(impl2_def_id);
75
+ let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
76
+ let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
77
+
78
+ // Check if any of the input types definitely mismatch.
79
+ if impl1_ref
80
+ .iter()
81
+ .flat_map(|tref| tref.substs.types())
82
+ .zip(impl2_ref.iter().flat_map(|tref| tref.substs.types()))
83
+ .chain(iter::once((impl1_self, impl2_self)))
84
+ .any(|(ty1, ty2)| {
85
+ let ty1 = fast_reject::simplify_type(tcx, ty1, false);
86
+ let ty2 = fast_reject::simplify_type(tcx, ty2, false);
87
+ if let (Some(ty1), Some(ty2)) = (ty1, ty2) {
88
+ // Simplified successfully
89
+ ty1 != ty2
90
+ } else {
91
+ // Types might unify
92
+ false
93
+ }
94
+ })
95
+ {
96
+ // Some types involved are definitely different, so the impls couldn't possibly overlap.
97
+ debug!("overlapping_impls: fast_reject early-exit");
98
+ return no_overlap();
99
+ }
70
100
71
101
let overlaps = tcx.infer_ctxt().enter(|infcx| {
72
102
let selcx = &mut SelectionContext::intercrate(&infcx);
0 commit comments