@@ -11,7 +11,7 @@ use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionCont
1111use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
1212use rustc_middle:: ty:: fold:: TypeFoldable ;
1313use rustc_middle:: ty:: subst:: Subst ;
14- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
14+ use rustc_middle:: ty:: { self , fast_reject , Ty , TyCtxt } ;
1515use rustc_span:: symbol:: sym;
1616use rustc_span:: DUMMY_SP ;
1717use std:: iter;
6767 impl2_def_id={:?})",
6868 impl1_def_id, impl2_def_id,
6969 ) ;
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+ }
70100
71101 let overlaps = tcx. infer_ctxt ( ) . enter ( |infcx| {
72102 let selcx = & mut SelectionContext :: intercrate ( & infcx) ;
0 commit comments