@@ -17,6 +17,7 @@ use crate::traits::{
1717use rustc_errors:: Diagnostic ;
1818use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
1919use rustc_hir:: CRATE_HIR_ID ;
20+ use rustc_infer:: infer:: at:: ToTrace ;
2021use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
2122use rustc_infer:: traits:: { util, TraitEngine } ;
2223use rustc_middle:: traits:: specialization_graph:: OverlapMode ;
@@ -26,6 +27,7 @@ use rustc_middle::ty::subst::Subst;
2627use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
2728use rustc_span:: symbol:: sym;
2829use rustc_span:: DUMMY_SP ;
30+ use std:: fmt:: Debug ;
2931use std:: iter;
3032
3133/// Whether we do the orphan check relative to this crate or
@@ -327,56 +329,56 @@ fn negative_impl<'cx, 'tcx>(
327329 let ( impl2_trait_ref, obligations) =
328330 impl_trait_ref_and_oblig ( selcx, impl1_env, impl2_def_id, impl2_substs) ;
329331
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) else {
334- debug ! (
335- "explicit_disjoint: {:?} does not unify with {:?}" ,
336- impl1_trait_ref, impl2_trait_ref
337- ) ;
338- return false ;
339- } ;
340-
341- let opt_failing_obligation = obligations
342- . into_iter ( )
343- . chain ( more_obligations)
344- . find ( |o| negative_impl_exists ( selcx, impl1_env, impl1_def_id, o) ) ;
345-
346- if let Some ( failing_obligation) = opt_failing_obligation {
347- debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
348- true
349- } else {
350- false
351- }
332+ !obligations_satisfiable (
333+ & infcx,
334+ impl1_env,
335+ impl1_def_id,
336+ impl1_trait_ref,
337+ impl2_trait_ref,
338+ obligations,
339+ )
352340 } else {
353341 let ty1 = tcx. type_of ( impl1_def_id) ;
354342 let ty2 = tcx. type_of ( impl2_def_id) ;
355343
356- let Ok ( InferOk { obligations, .. } ) = infcx
357- . at ( & ObligationCause :: dummy ( ) , impl1_env)
358- . eq ( ty1, ty2) else {
359- debug ! (
360- "explicit_disjoint: {:?} does not unify with {:?}" ,
361- ty1, ty2
362- ) ;
363- return false ;
364- } ;
365-
366- let opt_failing_obligation = obligations
367- . into_iter ( )
368- . find ( |o| negative_impl_exists ( selcx, impl1_env, impl1_def_id, o) ) ;
369-
370- if let Some ( failing_obligation) = opt_failing_obligation {
371- debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
372- true
373- } else {
374- false
375- }
344+ !obligations_satisfiable ( & infcx, impl1_env, impl1_def_id, ty1, ty2, iter:: empty ( ) )
376345 }
377346 } )
378347}
379348
349+ fn obligations_satisfiable < ' cx , ' tcx , T : Debug + ToTrace < ' tcx > > (
350+ infcx : & InferCtxt < ' cx , ' tcx > ,
351+ impl1_env : ty:: ParamEnv < ' tcx > ,
352+ impl1_def_id : DefId ,
353+ impl1 : T ,
354+ impl2 : T ,
355+ obligations : impl Iterator < Item = PredicateObligation < ' tcx > > ,
356+ ) -> bool {
357+ // do the impls unify? If not, not disjoint.
358+ let Ok ( InferOk { obligations : more_obligations, .. } ) = infcx
359+ . at ( & ObligationCause :: dummy ( ) , impl1_env)
360+ . eq ( impl1, impl2) else {
361+ debug ! (
362+ "explicit_disjoint: {:?} does not unify with {:?}" ,
363+ impl1, impl2
364+ ) ;
365+ return true ;
366+ } ;
367+
368+ let selcx = & mut SelectionContext :: new ( & infcx) ;
369+ let opt_failing_obligation = obligations
370+ . into_iter ( )
371+ . chain ( more_obligations)
372+ . find ( |o| negative_impl_exists ( selcx, impl1_env, impl1_def_id, o) ) ;
373+
374+ if let Some ( failing_obligation) = opt_failing_obligation {
375+ debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
376+ false
377+ } else {
378+ true
379+ }
380+ }
381+
380382/// Try to prove that a negative impl exist for the given obligation and their super predicates.
381383#[ instrument( level = "debug" , skip( selcx) ) ]
382384fn negative_impl_exists < ' cx , ' tcx > (
0 commit comments