@@ -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,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
126145 if !may_overlap {
127146 // Some types involved are definitely different, so the impls couldn't possibly overlap.
128147 debug ! ( "overlapping_impls: fast_reject early-exit" ) ;
129148 return 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 < ' _ > > {
132162 if tcx. next_trait_solver_in_coherence ( ) {
133163 overlap (
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 {
142173 let _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 ( ) ;
163196 Some ( 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 > {
168205 let tcx = infcx. tcx ;
169206 let impl_args = infcx. fresh_args_for_item ( DUMMY_SP , impl_def_id) ;
170207
171208 ImplHeader {
172209 impl_def_id,
173210 impl_args,
174211 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) ) ,
212+ trait_ref : is_of_trait
213+ . then ( || tcx. impl_trait_ref ( impl_def_id) . unwrap ( ) . instantiate ( tcx, impl_args) ) ,
176214 predicates : tcx
177215 . predicates_of ( impl_def_id)
178216 . instantiate ( tcx, impl_args)
@@ -186,8 +224,9 @@ fn fresh_impl_header_normalized<'tcx>(
186224 infcx : & InferCtxt < ' tcx > ,
187225 param_env : ty:: ParamEnv < ' tcx > ,
188226 impl_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
192231 let InferOk { value : mut header, obligations } =
193232 infcx. at ( & ObligationCause :: dummy ( ) , param_env) . normalize ( header) ;
@@ -206,10 +245,16 @@ fn overlap<'tcx>(
206245 impl1_def_id : DefId ,
207246 impl2_def_id : DefId ,
208247 overlap_mode : OverlapMode ,
248+ is_of_trait : bool ,
209249) -> Option < OverlapResult < ' tcx > > {
210250 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)
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 {
214259 return None ;
215260 }
@@ -231,8 +276,10 @@ fn overlap<'tcx>(
231276 // empty environment.
232277 let 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(
446493 tcx : TyCtxt < ' _ > ,
447494 impl1_def_id : DefId ,
448495 impl2_def_id : DefId ,
496+ is_of_trait : bool ,
449497) -> bool {
450498 debug ! ( "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(
455503 let root_universe = infcx. universe ( ) ;
456504 assert_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 ) ;
459507 let 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