@@ -100,7 +100,7 @@ impl TrackAmbiguityCauses {
100
100
/// with a suitably-freshened `ImplHeader` with those types
101
101
/// instantiated. Otherwise, returns `None`.
102
102
#[ instrument( skip( tcx, skip_leak_check) , level = "debug" ) ]
103
- pub fn overlapping_impls (
103
+ pub fn overlapping_inherent_impls (
104
104
tcx : TyCtxt < ' _ > ,
105
105
impl1_def_id : DefId ,
106
106
impl2_def_id : DefId ,
@@ -110,25 +110,55 @@ pub fn overlapping_impls(
110
110
// Before doing expensive operations like entering an inference context, do
111
111
// a quick check via fast_reject to tell if the impl headers could possibly
112
112
// 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) ;
125
144
126
145
if !may_overlap {
127
146
// Some types involved are definitely different, so the impls couldn't possibly overlap.
128
147
debug ! ( "overlapping_impls: fast_reject early-exit" ) ;
129
148
return None ;
130
149
}
131
150
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 < ' _ > > {
132
162
if tcx. next_trait_solver_in_coherence ( ) {
133
163
overlap (
134
164
tcx,
@@ -137,6 +167,7 @@ pub fn overlapping_impls(
137
167
impl1_def_id,
138
168
impl2_def_id,
139
169
overlap_mode,
170
+ is_of_trait,
140
171
)
141
172
} else {
142
173
let _overlap_with_bad_diagnostics = overlap (
@@ -146,6 +177,7 @@ pub fn overlapping_impls(
146
177
impl1_def_id,
147
178
impl2_def_id,
148
179
overlap_mode,
180
+ is_of_trait,
149
181
) ?;
150
182
151
183
// In the case where we detect an error, run the check again, but
@@ -158,21 +190,27 @@ pub fn overlapping_impls(
158
190
impl1_def_id,
159
191
impl2_def_id,
160
192
overlap_mode,
193
+ is_of_trait,
161
194
)
162
195
. unwrap ( ) ;
163
196
Some ( overlap)
164
197
}
165
198
}
166
199
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 > {
168
205
let tcx = infcx. tcx ;
169
206
let impl_args = infcx. fresh_args_for_item ( DUMMY_SP , impl_def_id) ;
170
207
171
208
ImplHeader {
172
209
impl_def_id,
173
210
impl_args,
174
211
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) ) ,
176
214
predicates : tcx
177
215
. predicates_of ( impl_def_id)
178
216
. instantiate ( tcx, impl_args)
@@ -186,8 +224,9 @@ fn fresh_impl_header_normalized<'tcx>(
186
224
infcx : & InferCtxt < ' tcx > ,
187
225
param_env : ty:: ParamEnv < ' tcx > ,
188
226
impl_def_id : DefId ,
227
+ is_of_trait : bool ,
189
228
) -> 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 ) ;
191
230
192
231
let InferOk { value : mut header, obligations } =
193
232
infcx. at ( & ObligationCause :: dummy ( ) , param_env) . normalize ( header) ;
@@ -206,10 +245,16 @@ fn overlap<'tcx>(
206
245
impl1_def_id : DefId ,
207
246
impl2_def_id : DefId ,
208
247
overlap_mode : OverlapMode ,
248
+ is_of_trait : bool ,
209
249
) -> Option < OverlapResult < ' tcx > > {
210
250
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
+ )
213
258
{
214
259
return None ;
215
260
}
@@ -231,8 +276,10 @@ fn overlap<'tcx>(
231
276
// empty environment.
232
277
let param_env = ty:: ParamEnv :: empty ( ) ;
233
278
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) ;
236
283
237
284
// Equate the headers to find their intersection (the general type, with infer vars,
238
285
// that may apply both impls).
@@ -446,6 +493,7 @@ fn impl_intersection_has_negative_obligation(
446
493
tcx : TyCtxt < ' _ > ,
447
494
impl1_def_id : DefId ,
448
495
impl2_def_id : DefId ,
496
+ is_of_trait : bool ,
449
497
) -> bool {
450
498
debug ! ( "negative_impl(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
451
499
@@ -455,11 +503,11 @@ fn impl_intersection_has_negative_obligation(
455
503
let root_universe = infcx. universe ( ) ;
456
504
assert_eq ! ( root_universe, ty:: UniverseIndex :: ROOT ) ;
457
505
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 ) ;
459
507
let param_env =
460
508
ty:: EarlyBinder :: bind ( tcx. param_env ( impl1_def_id) ) . instantiate ( tcx, impl1_header. impl_args ) ;
461
509
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 ) ;
463
511
464
512
// Equate the headers to find their intersection (the general type, with infer vars,
465
513
// that may apply both impls).
0 commit comments