@@ -100,7 +100,7 @@ impl TrackAmbiguityCauses {
100100/// with a suitably-freshened `ImplHeader` with those types
101101/// instantiated. Otherwise, returns `None`.
102102#[ instrument( skip( tcx, skip_leak_check) , level = "debug" ) ]
103- pub fn overlapping_impls (
103+ pub fn overlapping_inherent_impls (
104104tcx : TyCtxt < ' _ > ,
105105impl1_def_id : DefId ,
106106impl2_def_id : DefId ,
@@ -110,25 +110,55 @@ pub fn overlapping_impls(
110110// Before doing expensive operations like entering an inference context, do
111111// a quick check via fast_reject to tell if the impl headers could possibly
112112// unify.
113- let drcx = DeepRejectCtxt :: relate_infer_infer ( tcx) ;
114- let impl1_ref = tcx. impl_trait_ref ( impl1_def_id) ;
115- let impl2_ref = tcx. impl_trait_ref ( impl2_def_id) ;
116- let may_overlap = match ( impl1_ref, impl2_ref) {
117- ( Some ( a) , Some ( b) ) => drcx. args_may_unify ( a. skip_binder ( ) . args , b. skip_binder ( ) . args ) ,
118- ( None , None ) => {
119- let self_ty1 = tcx. type_of ( impl1_def_id) . skip_binder ( ) ;
120- let self_ty2 = tcx. type_of ( impl2_def_id) . skip_binder ( ) ;
121- drcx. types_may_unify ( self_ty1, self_ty2)
122- }
123- _ => bug ! ( "unexpected impls: {impl1_def_id:?} {impl2_def_id:?}" ) ,
124- } ;
113+ let self_ty1 = tcx. type_of ( impl1_def_id) . skip_binder ( ) ;
114+ let self_ty2 = tcx. type_of ( impl2_def_id) . skip_binder ( ) ;
115+ let may_overlap = DeepRejectCtxt :: relate_infer_infer ( tcx) . types_may_unify ( self_ty1, self_ty2) ;
116+
117+ if !may_overlap {
118+ // Some types involved are definitely different, so the impls couldn't possibly overlap.
119+ debug ! ( "overlapping_inherent_impls: fast_reject early-exit" ) ;
120+ return None ;
121+ }
122+
123+ overlapping_impls ( tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, false )
124+ }
125+
126+ /// If there are types that satisfy both impls, returns `Some`
127+ /// with a suitably-freshened `ImplHeader` with those types
128+ /// instantiated. Otherwise, returns `None`.
129+ #[ instrument( skip( tcx, skip_leak_check) , level = "debug" ) ]
130+ pub fn overlapping_trait_impls (
131+ tcx : TyCtxt < ' _ > ,
132+ impl1_def_id : DefId ,
133+ impl2_def_id : DefId ,
134+ skip_leak_check : SkipLeakCheck ,
135+ overlap_mode : OverlapMode ,
136+ ) -> Option < OverlapResult < ' _ > > {
137+ // Before doing expensive operations like entering an inference context, do
138+ // a quick check via fast_reject to tell if the impl headers could possibly
139+ // unify.
140+ let impl1_args = tcx. impl_trait_ref ( impl1_def_id) . unwrap ( ) . skip_binder ( ) . args ;
141+ let impl2_args = tcx. impl_trait_ref ( impl2_def_id) . unwrap ( ) . skip_binder ( ) . args ;
142+ let may_overlap =
143+ DeepRejectCtxt :: relate_infer_infer ( tcx) . args_may_unify ( impl1_args, impl2_args) ;
125144
126145if !may_overlap {
127146// Some types involved are definitely different, so the impls couldn't possibly overlap.
128147debug ! ( "overlapping_impls: fast_reject early-exit" ) ;
129148return None ;
130149}
131150
151+ overlapping_impls ( tcx, impl1_def_id, impl2_def_id, skip_leak_check, overlap_mode, true )
152+ }
153+
154+ fn overlapping_impls (
155+ tcx : TyCtxt < ' _ > ,
156+ impl1_def_id : DefId ,
157+ impl2_def_id : DefId ,
158+ skip_leak_check : SkipLeakCheck ,
159+ overlap_mode : OverlapMode ,
160+ is_of_trait : bool ,
161+ ) -> Option < OverlapResult < ' _ > > {
132162if tcx. next_trait_solver_in_coherence ( ) {
133163overlap (
134164 tcx,
@@ -137,6 +167,7 @@ pub fn overlapping_impls(
137167 impl1_def_id,
138168 impl2_def_id,
139169 overlap_mode,
170+ is_of_trait,
140171)
141172} else {
142173let _overlap_with_bad_diagnostics = overlap (
@@ -146,6 +177,7 @@ pub fn overlapping_impls(
146177 impl1_def_id,
147178 impl2_def_id,
148179 overlap_mode,
180+ is_of_trait,
149181) ?;
150182
151183// In the case where we detect an error, run the check again, but
@@ -158,21 +190,27 @@ pub fn overlapping_impls(
158190 impl1_def_id,
159191 impl2_def_id,
160192 overlap_mode,
193+ is_of_trait,
161194)
162195. unwrap ( ) ;
163196Some ( overlap)
164197}
165198}
166199
167- fn fresh_impl_header < ' tcx > ( infcx : & InferCtxt < ' tcx > , impl_def_id : DefId ) -> ImplHeader < ' tcx > {
200+ fn fresh_impl_header < ' tcx > (
201+ infcx : & InferCtxt < ' tcx > ,
202+ impl_def_id : DefId ,
203+ is_of_trait : bool ,
204+ ) -> ImplHeader < ' tcx > {
168205let tcx = infcx. tcx ;
169206let impl_args = infcx. fresh_args_for_item ( DUMMY_SP , impl_def_id) ;
170207
171208ImplHeader {
172209 impl_def_id,
173210 impl_args,
174211self_ty : tcx. type_of ( impl_def_id) . instantiate ( tcx, impl_args) ,
175- trait_ref : tcx. impl_trait_ref ( impl_def_id) . map ( |i| i. instantiate ( tcx, impl_args) ) ,
212+ trait_ref : is_of_trait
213+ . then ( || tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) . instantiate ( tcx, impl_args) ) ,
176214predicates : tcx
177215. predicates_of ( impl_def_id)
178216. instantiate ( tcx, impl_args)
@@ -186,8 +224,9 @@ fn fresh_impl_header_normalized<'tcx>(
186224infcx : & InferCtxt < ' tcx > ,
187225param_env : ty:: ParamEnv < ' tcx > ,
188226impl_def_id : DefId ,
227+ is_of_trait : bool ,
189228) -> ImplHeader < ' tcx > {
190- let header = fresh_impl_header ( infcx, impl_def_id) ;
229+ let header = fresh_impl_header ( infcx, impl_def_id, is_of_trait ) ;
191230
192231let InferOk { value : mut header, obligations } =
193232 infcx. at ( & ObligationCause :: dummy ( ) , param_env) . normalize ( header) ;
@@ -206,10 +245,16 @@ fn overlap<'tcx>(
206245impl1_def_id : DefId ,
207246impl2_def_id : DefId ,
208247overlap_mode : OverlapMode ,
248+ is_of_trait : bool ,
209249) -> Option < OverlapResult < ' tcx > > {
210250if overlap_mode. use_negative_impl ( ) {
211- if impl_intersection_has_negative_obligation ( tcx, impl1_def_id, impl2_def_id)
212- || impl_intersection_has_negative_obligation ( tcx, impl2_def_id, impl1_def_id)
251+ if impl_intersection_has_negative_obligation ( tcx, impl1_def_id, impl2_def_id, is_of_trait)
252+ || impl_intersection_has_negative_obligation (
253+ tcx,
254+ impl2_def_id,
255+ impl1_def_id,
256+ is_of_trait,
257+ )
213258{
214259return None ;
215260}
@@ -231,8 +276,10 @@ fn overlap<'tcx>(
231276// empty environment.
232277let param_env = ty:: ParamEnv :: empty ( ) ;
233278
234- let impl1_header = fresh_impl_header_normalized ( selcx. infcx , param_env, impl1_def_id) ;
235- let impl2_header = fresh_impl_header_normalized ( selcx. infcx , param_env, impl2_def_id) ;
279+ let impl1_header =
280+ fresh_impl_header_normalized ( selcx. infcx , param_env, impl1_def_id, is_of_trait) ;
281+ let impl2_header =
282+ fresh_impl_header_normalized ( selcx. infcx , param_env, impl2_def_id, is_of_trait) ;
236283
237284// Equate the headers to find their intersection (the general type, with infer vars,
238285// that may apply both impls).
@@ -446,6 +493,7 @@ fn impl_intersection_has_negative_obligation(
446493tcx : TyCtxt < ' _ > ,
447494impl1_def_id : DefId ,
448495impl2_def_id : DefId ,
496+ is_of_trait : bool ,
449497) -> bool {
450498debug ! ( "negative_impl(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
451499
@@ -455,11 +503,11 @@ fn impl_intersection_has_negative_obligation(
455503let root_universe = infcx. universe ( ) ;
456504assert_eq ! ( root_universe, ty:: UniverseIndex :: ROOT ) ;
457505
458- let impl1_header = fresh_impl_header ( infcx, impl1_def_id) ;
506+ let impl1_header = fresh_impl_header ( infcx, impl1_def_id, is_of_trait ) ;
459507let param_env =
460508 ty:: EarlyBinder :: bind ( tcx. param_env ( impl1_def_id) ) . instantiate ( tcx, impl1_header. impl_args ) ;
461509
462- let impl2_header = fresh_impl_header ( infcx, impl2_def_id) ;
510+ let impl2_header = fresh_impl_header ( infcx, impl2_def_id, is_of_trait ) ;
463511
464512// Equate the headers to find their intersection (the general type, with infer vars,
465513// that may apply both impls).
0 commit comments