@@ -11,10 +11,11 @@ use crate::traits::SkipLeakCheck;
1111use crate :: traits:: { self , Normalized , Obligation , ObligationCause , SelectionContext } ;
1212use crate :: ty:: fold:: TypeFoldable ;
1313use crate :: ty:: subst:: Subst ;
14- use crate :: ty:: { self , Ty , TyCtxt } ;
14+ use crate :: ty:: { self , fast_reject , Ty , TyCtxt } ;
1515use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
1616use rustc_span:: symbol:: sym;
1717use rustc_span:: DUMMY_SP ;
18+ use std:: iter;
1819
1920/// Whether we do the orphan check relative to this crate or
2021/// to some remote crate.
7071 impl1_def_id, impl2_def_id, intercrate_mode
7172 ) ;
7273
74+ // Before doing expensive operations like entering an inference context, do
75+ // a quick check via fast_reject to tell if the impl headers could possibly
76+ // unify.
77+ let impl1_self = tcx. type_of ( impl1_def_id) ;
78+ let impl2_self = tcx. type_of ( impl2_def_id) ;
79+ let impl1_ref = tcx. impl_trait_ref ( impl1_def_id) ;
80+ let impl2_ref = tcx. impl_trait_ref ( impl2_def_id) ;
81+
82+ // Check if any of the input types definitely mismatch.
83+ if impl1_ref
84+ . iter ( )
85+ . flat_map ( |tref| tref. input_types ( ) )
86+ . zip ( impl2_ref. iter ( ) . flat_map ( |tref| tref. input_types ( ) ) )
87+ . chain ( iter:: once ( ( impl1_self, impl2_self) ) )
88+ . any ( |( ty1, ty2) | {
89+ let ty1 = fast_reject:: simplify_type ( tcx, ty1, false ) ;
90+ let ty2 = fast_reject:: simplify_type ( tcx, ty2, false ) ;
91+ if let ( Some ( ty1) , Some ( ty2) ) = ( ty1, ty2) {
92+ // Simplified successfully
93+ ty1 != ty2
94+ } else {
95+ // Types might unify
96+ false
97+ }
98+ } )
99+ {
100+ // Some types involved are definitely different, so the impls couldn't possibly overlap.
101+ debug ! ( "overlapping_impls: fast_reject early-exit" ) ;
102+ return no_overlap ( ) ;
103+ }
104+
73105 let overlaps = tcx. infer_ctxt ( ) . enter ( |infcx| {
74106 let selcx = & mut SelectionContext :: intercrate ( & infcx, intercrate_mode) ;
75107 overlap ( selcx, skip_leak_check, impl1_def_id, impl2_def_id) . is_some ( )
0 commit comments