77use crate :: infer:: outlives:: env:: OutlivesEnvironment ;
88use crate :: infer:: { CombinedSnapshot , InferOk , RegionckMode } ;
99use crate :: traits:: select:: IntercrateAmbiguityCause ;
10- use crate :: traits:: util:: impl_trait_ref_and_oblig ;
10+ use crate :: traits:: util:: impl_subject_and_oblig ;
1111use crate :: traits:: SkipLeakCheck ;
1212use crate :: traits:: {
1313 self , FulfillmentContext , Normalized , Obligation , ObligationCause , PredicateObligation ,
@@ -23,9 +23,10 @@ use rustc_middle::traits::specialization_graph::OverlapMode;
2323use rustc_middle:: ty:: fast_reject:: { self , TreatParams } ;
2424use rustc_middle:: ty:: fold:: TypeFoldable ;
2525use rustc_middle:: ty:: subst:: Subst ;
26- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
26+ use rustc_middle:: ty:: { self , ImplSubject , Ty , TyCtxt } ;
2727use rustc_span:: symbol:: sym;
2828use rustc_span:: DUMMY_SP ;
29+ use std:: fmt:: Debug ;
2930use std:: iter;
3031
3132/// Whether we do the orphan check relative to this crate or
@@ -300,60 +301,62 @@ fn negative_impl<'cx, 'tcx>(
300301 debug ! ( "negative_impl(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
301302 let tcx = selcx. infcx ( ) . tcx ;
302303
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-
307304 // Create an infcx, taking the predicates of impl1 as assumptions:
308305 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 (
312309 & infcx,
313310 FulfillmentContext :: new ( ) ,
314311 ObligationCause :: dummy ( ) ,
315- impl1_env ,
316- impl1_trait_ref ,
312+ impl_env ,
313+ tcx . impl_subject ( impl1_def_id ) ,
317314 ) {
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) ,
322317 } ;
323318
324319 // Attempt to prove that impl2 applies, given all of the above.
325320 let selcx = & mut SelectionContext :: new ( & infcx) ;
326321 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) ;
341324
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)
353326 } )
354327}
355328
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.
357360#[ instrument( level = "debug" , skip( selcx) ) ]
358361fn negative_impl_exists < ' cx , ' tcx > (
359362 selcx : & SelectionContext < ' cx , ' tcx > ,
@@ -367,7 +370,7 @@ fn negative_impl_exists<'cx, 'tcx>(
367370 return true ;
368371 }
369372
370- // Try to prove a negative obligation exist for super predicates
373+ // Try to prove a negative obligation exists for super predicates
371374 for o in util:: elaborate_predicates ( infcx. tcx , iter:: once ( o. predicate ) ) {
372375 if resolve_negative_obligation ( infcx, param_env, region_context, & o) {
373376 return true ;
0 commit comments