@@ -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 (
104104 tcx : TyCtxt < ' _ > ,
105105 impl1_def_id : DefId ,
106106 impl2_def_id : DefId ,
@@ -110,32 +110,75 @@ 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, None , impl2_def_id, None , skip_leak_check, overlap_mode)
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_trait_ref = tcx. impl_trait_ref ( impl1_def_id) . unwrap ( ) ;
141+ let impl2_trait_ref = tcx. impl_trait_ref ( impl2_def_id) . unwrap ( ) ;
142+ let impl1_args = impl1_trait_ref. skip_binder ( ) . args ;
143+ let impl2_args = impl2_trait_ref. skip_binder ( ) . args ;
144+ let may_overlap =
145+ DeepRejectCtxt :: relate_infer_infer ( tcx) . args_may_unify ( impl1_args, impl2_args) ;
125146
126147 if !may_overlap {
127148 // Some types involved are definitely different, so the impls couldn't possibly overlap.
128149 debug ! ( "overlapping_impls: fast_reject early-exit" ) ;
129150 return None ;
130151 }
131152
153+ overlapping_impls (
154+ tcx,
155+ impl1_def_id,
156+ Some ( impl1_trait_ref) ,
157+ impl2_def_id,
158+ Some ( impl2_trait_ref) ,
159+ skip_leak_check,
160+ overlap_mode,
161+ )
162+ }
163+
164+ fn overlapping_impls < ' tcx > (
165+ tcx : TyCtxt < ' tcx > ,
166+ impl1_def_id : DefId ,
167+ impl1_trait_ref : Option < ty:: EarlyBinder < ' tcx , ty:: TraitRef < ' tcx > > > ,
168+ impl2_def_id : DefId ,
169+ impl2_trait_ref : Option < ty:: EarlyBinder < ' tcx , ty:: TraitRef < ' tcx > > > ,
170+ skip_leak_check : SkipLeakCheck ,
171+ overlap_mode : OverlapMode ,
172+ ) -> Option < OverlapResult < ' tcx > > {
132173 if tcx. next_trait_solver_in_coherence ( ) {
133174 overlap (
134175 tcx,
135176 TrackAmbiguityCauses :: Yes ,
136177 skip_leak_check,
137178 impl1_def_id,
179+ impl1_trait_ref,
138180 impl2_def_id,
181+ impl2_trait_ref,
139182 overlap_mode,
140183 )
141184 } else {
@@ -144,7 +187,9 @@ pub fn overlapping_impls(
144187 TrackAmbiguityCauses :: No ,
145188 skip_leak_check,
146189 impl1_def_id,
190+ impl1_trait_ref,
147191 impl2_def_id,
192+ impl2_trait_ref,
148193 overlap_mode,
149194 ) ?;
150195
@@ -156,23 +201,29 @@ pub fn overlapping_impls(
156201 TrackAmbiguityCauses :: Yes ,
157202 skip_leak_check,
158203 impl1_def_id,
204+ impl1_trait_ref,
159205 impl2_def_id,
206+ impl2_trait_ref,
160207 overlap_mode,
161208 )
162209 . unwrap ( ) ;
163210 Some ( overlap)
164211 }
165212}
166213
167- fn fresh_impl_header < ' tcx > ( infcx : & InferCtxt < ' tcx > , impl_def_id : DefId ) -> ImplHeader < ' tcx > {
214+ fn fresh_impl_header < ' tcx > (
215+ infcx : & InferCtxt < ' tcx > ,
216+ impl_def_id : DefId ,
217+ trait_ref : Option < ty:: EarlyBinder < ' tcx , ty:: TraitRef < ' tcx > > > ,
218+ ) -> ImplHeader < ' tcx > {
168219 let tcx = infcx. tcx ;
169220 let impl_args = infcx. fresh_args_for_item ( DUMMY_SP , impl_def_id) ;
170221
171222 ImplHeader {
172223 impl_def_id,
173224 impl_args,
174225 self_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) ) ,
226+ trait_ref : trait_ref . map ( |trait_ref| trait_ref . instantiate ( tcx, impl_args) ) ,
176227 predicates : tcx
177228 . predicates_of ( impl_def_id)
178229 . instantiate ( tcx, impl_args)
@@ -186,8 +237,9 @@ fn fresh_impl_header_normalized<'tcx>(
186237 infcx : & InferCtxt < ' tcx > ,
187238 param_env : ty:: ParamEnv < ' tcx > ,
188239 impl_def_id : DefId ,
240+ trait_ref : Option < ty:: EarlyBinder < ' tcx , ty:: TraitRef < ' tcx > > > ,
189241) -> ImplHeader < ' tcx > {
190- let header = fresh_impl_header ( infcx, impl_def_id) ;
242+ let header = fresh_impl_header ( infcx, impl_def_id, trait_ref ) ;
191243
192244 let InferOk { value : mut header, obligations } =
193245 infcx. at ( & ObligationCause :: dummy ( ) , param_env) . normalize ( header) ;
@@ -204,13 +256,25 @@ fn overlap<'tcx>(
204256 track_ambiguity_causes : TrackAmbiguityCauses ,
205257 skip_leak_check : SkipLeakCheck ,
206258 impl1_def_id : DefId ,
259+ impl1_trait_ref : Option < ty:: EarlyBinder < ' tcx , ty:: TraitRef < ' tcx > > > ,
207260 impl2_def_id : DefId ,
261+ impl2_trait_ref : Option < ty:: EarlyBinder < ' tcx , ty:: TraitRef < ' tcx > > > ,
208262 overlap_mode : OverlapMode ,
209263) -> Option < OverlapResult < ' tcx > > {
210264 if 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)
213- {
265+ if impl_intersection_has_negative_obligation (
266+ tcx,
267+ impl1_def_id,
268+ impl1_trait_ref,
269+ impl2_def_id,
270+ impl2_trait_ref,
271+ ) || impl_intersection_has_negative_obligation (
272+ tcx,
273+ impl2_def_id,
274+ impl2_trait_ref,
275+ impl1_def_id,
276+ impl1_trait_ref,
277+ ) {
214278 return None ;
215279 }
216280 }
@@ -231,8 +295,10 @@ fn overlap<'tcx>(
231295 // empty environment.
232296 let param_env = ty:: ParamEnv :: empty ( ) ;
233297
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) ;
298+ let impl1_header =
299+ fresh_impl_header_normalized ( selcx. infcx , param_env, impl1_def_id, impl1_trait_ref) ;
300+ let impl2_header =
301+ fresh_impl_header_normalized ( selcx. infcx , param_env, impl2_def_id, impl2_trait_ref) ;
236302
237303 // Equate the headers to find their intersection (the general type, with infer vars,
238304 // that may apply both impls).
@@ -442,10 +508,12 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
442508/// after negating, giving us `&str: !Error`. This is a negative impl provided by
443509/// libstd, and therefore we can guarantee for certain that libstd will never add
444510/// a positive impl for `&str: Error` (without it being a breaking change).
445- fn impl_intersection_has_negative_obligation (
446- tcx : TyCtxt < ' _ > ,
511+ fn impl_intersection_has_negative_obligation < ' tcx > (
512+ tcx : TyCtxt < ' tcx > ,
447513 impl1_def_id : DefId ,
514+ impl1_trait_ref : Option < ty:: EarlyBinder < ' tcx , ty:: TraitRef < ' tcx > > > ,
448515 impl2_def_id : DefId ,
516+ impl2_trait_ref : Option < ty:: EarlyBinder < ' tcx , ty:: TraitRef < ' tcx > > > ,
449517) -> bool {
450518 debug ! ( "negative_impl(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
451519
@@ -455,11 +523,11 @@ fn impl_intersection_has_negative_obligation(
455523 let root_universe = infcx. universe ( ) ;
456524 assert_eq ! ( root_universe, ty:: UniverseIndex :: ROOT ) ;
457525
458- let impl1_header = fresh_impl_header ( infcx, impl1_def_id) ;
526+ let impl1_header = fresh_impl_header ( infcx, impl1_def_id, impl1_trait_ref ) ;
459527 let param_env =
460528 ty:: EarlyBinder :: bind ( tcx. param_env ( impl1_def_id) ) . instantiate ( tcx, impl1_header. impl_args ) ;
461529
462- let impl2_header = fresh_impl_header ( infcx, impl2_def_id) ;
530+ let impl2_header = fresh_impl_header ( infcx, impl2_def_id, impl2_trait_ref ) ;
463531
464532 // Equate the headers to find their intersection (the general type, with infer vars,
465533 // that may apply both impls).
0 commit comments