7
7
use crate :: infer:: outlives:: env:: OutlivesEnvironment ;
8
8
use crate :: infer:: { CombinedSnapshot , InferOk , RegionckMode } ;
9
9
use crate :: traits:: select:: IntercrateAmbiguityCause ;
10
- use crate :: traits:: util:: impl_trait_ref_and_oblig ;
10
+ use crate :: traits:: util:: impl_subject_and_oblig ;
11
11
use crate :: traits:: SkipLeakCheck ;
12
12
use crate :: traits:: {
13
13
self , FulfillmentContext , Normalized , Obligation , ObligationCause , PredicateObligation ,
@@ -23,9 +23,10 @@ use rustc_middle::traits::specialization_graph::OverlapMode;
23
23
use rustc_middle:: ty:: fast_reject:: { self , TreatParams } ;
24
24
use rustc_middle:: ty:: fold:: TypeFoldable ;
25
25
use rustc_middle:: ty:: subst:: Subst ;
26
- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
26
+ use rustc_middle:: ty:: { self , ImplSubject , Ty , TyCtxt } ;
27
27
use rustc_span:: symbol:: sym;
28
28
use rustc_span:: DUMMY_SP ;
29
+ use std:: fmt:: Debug ;
29
30
use std:: iter;
30
31
31
32
/// Whether we do the orphan check relative to this crate or
@@ -300,60 +301,62 @@ fn negative_impl<'cx, 'tcx>(
300
301
debug ! ( "negative_impl(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
301
302
let tcx = selcx. infcx ( ) . tcx ;
302
303
303
- // create a parameter environment corresponding to a (placeholder) instantiation of impl1
304
- let impl1_env = tcx. param_env ( impl1_def_id) ;
305
- let impl1_trait_ref = tcx. impl_trait_ref ( impl1_def_id) . unwrap ( ) ;
306
-
307
304
// Create an infcx, taking the predicates of impl1 as assumptions:
308
305
tcx. infer_ctxt ( ) . enter ( |infcx| {
309
- // Normalize the trait reference. The WF rules ought to ensure
310
- // that this always succeeds.
311
- let impl1_trait_ref = match traits:: fully_normalize (
306
+ // create a parameter environment corresponding to a (placeholder) instantiation of impl1
307
+ let impl_env = tcx . param_env ( impl1_def_id ) ;
308
+ let subject1 = match traits:: fully_normalize (
312
309
& infcx,
313
310
FulfillmentContext :: new ( ) ,
314
311
ObligationCause :: dummy ( ) ,
315
- impl1_env ,
316
- impl1_trait_ref ,
312
+ impl_env ,
313
+ tcx . impl_subject ( impl1_def_id ) ,
317
314
) {
318
- Ok ( impl1_trait_ref) => impl1_trait_ref,
319
- Err ( err) => {
320
- bug ! ( "failed to fully normalize {:?}: {:?}" , impl1_trait_ref, err) ;
321
- }
315
+ Ok ( s) => s,
316
+ Err ( err) => bug ! ( "failed to fully normalize {:?}: {:?}" , impl1_def_id, err) ,
322
317
} ;
323
318
324
319
// Attempt to prove that impl2 applies, given all of the above.
325
320
let selcx = & mut SelectionContext :: new ( & infcx) ;
326
321
let impl2_substs = infcx. fresh_substs_for_item ( DUMMY_SP , impl2_def_id) ;
327
- let ( impl2_trait_ref, obligations) =
328
- impl_trait_ref_and_oblig ( selcx, impl1_env, impl2_def_id, impl2_substs) ;
329
-
330
- // do the impls unify? If not, not disjoint.
331
- let Ok ( InferOk { obligations : more_obligations, .. } ) = infcx
332
- . at ( & ObligationCause :: dummy ( ) , impl1_env)
333
- . eq ( impl1_trait_ref, impl2_trait_ref)
334
- else {
335
- debug ! (
336
- "explicit_disjoint: {:?} does not unify with {:?}" ,
337
- impl1_trait_ref, impl2_trait_ref
338
- ) ;
339
- return false ;
340
- } ;
322
+ let ( subject2, obligations) =
323
+ impl_subject_and_oblig ( selcx, impl_env, impl2_def_id, impl2_substs) ;
341
324
342
- let opt_failing_obligation = obligations
343
- . into_iter ( )
344
- . chain ( more_obligations)
345
- . find ( |o| negative_impl_exists ( selcx, impl1_env, impl1_def_id, o) ) ;
346
-
347
- if let Some ( failing_obligation) = opt_failing_obligation {
348
- debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
349
- true
350
- } else {
351
- false
352
- }
325
+ !equate ( & infcx, impl_env, impl1_def_id, subject1, subject2, obligations)
353
326
} )
354
327
}
355
328
356
- /// Try to prove that a negative impl exist for the given obligation and their super predicates.
329
+ fn equate < ' cx , ' tcx > (
330
+ infcx : & InferCtxt < ' cx , ' tcx > ,
331
+ impl_env : ty:: ParamEnv < ' tcx > ,
332
+ impl1_def_id : DefId ,
333
+ subject1 : ImplSubject < ' tcx > ,
334
+ subject2 : ImplSubject < ' tcx > ,
335
+ obligations : impl Iterator < Item = PredicateObligation < ' tcx > > ,
336
+ ) -> bool {
337
+ // do the impls unify? If not, not disjoint.
338
+ let Ok ( InferOk { obligations : more_obligations, .. } ) =
339
+ infcx. at ( & ObligationCause :: dummy ( ) , impl_env) . eq ( subject1, subject2)
340
+ else {
341
+ debug ! ( "explicit_disjoint: {:?} does not unify with {:?}" , subject1, subject2) ;
342
+ return true ;
343
+ } ;
344
+
345
+ let selcx = & mut SelectionContext :: new ( & infcx) ;
346
+ let opt_failing_obligation = obligations
347
+ . into_iter ( )
348
+ . chain ( more_obligations)
349
+ . find ( |o| negative_impl_exists ( selcx, impl_env, impl1_def_id, o) ) ;
350
+
351
+ if let Some ( failing_obligation) = opt_failing_obligation {
352
+ debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
353
+ false
354
+ } else {
355
+ true
356
+ }
357
+ }
358
+
359
+ /// Try to prove that a negative impl exist for the given obligation and its super predicates.
357
360
#[ instrument( level = "debug" , skip( selcx) ) ]
358
361
fn negative_impl_exists < ' cx , ' tcx > (
359
362
selcx : & SelectionContext < ' cx , ' tcx > ,
@@ -367,7 +370,7 @@ fn negative_impl_exists<'cx, 'tcx>(
367
370
return true ;
368
371
}
369
372
370
- // Try to prove a negative obligation exist for super predicates
373
+ // Try to prove a negative obligation exists for super predicates
371
374
for o in util:: elaborate_predicates ( infcx. tcx , iter:: once ( o. predicate ) ) {
372
375
if resolve_negative_obligation ( infcx, param_env, region_context, & o) {
373
376
return true ;
0 commit comments