@@ -17,8 +17,8 @@ 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:: TyCtxtInferExt ;
21- use rustc_infer:: traits:: TraitEngine ;
20+ use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
21+ use rustc_infer:: traits:: { util , TraitEngine } ;
2222use rustc_middle:: traits:: specialization_graph:: OverlapMode ;
2323use rustc_middle:: ty:: fast_reject:: { self , TreatParams } ;
2424use rustc_middle:: ty:: fold:: TypeFoldable ;
@@ -353,49 +353,75 @@ fn negative_impl<'cx, 'tcx>(
353353 } )
354354}
355355
356+ /// Try to prove that a negative impl exist for the given obligation and their super predicates.
357+ #[ instrument( level = "debug" , skip( selcx) ) ]
356358fn negative_impl_exists < ' cx , ' tcx > (
357359 selcx : & SelectionContext < ' cx , ' tcx > ,
358360 param_env : ty:: ParamEnv < ' tcx > ,
359361 region_context : DefId ,
360362 o : & PredicateObligation < ' tcx > ,
361363) -> bool {
362364 let infcx = & selcx. infcx ( ) . fork ( ) ;
365+
366+ if resolve_negative_obligation ( infcx, param_env, region_context, o) {
367+ return true ;
368+ }
369+
370+ // Try to prove a negative obligation exist for super predicates
371+ for o in util:: elaborate_predicates ( infcx. tcx , iter:: once ( o. predicate ) ) {
372+ if resolve_negative_obligation ( infcx, param_env, region_context, & o) {
373+ return true ;
374+ }
375+ }
376+
377+ false
378+ }
379+
380+ #[ instrument( level = "debug" , skip( infcx) ) ]
381+ fn resolve_negative_obligation < ' cx , ' tcx > (
382+ infcx : & InferCtxt < ' cx , ' tcx > ,
383+ param_env : ty:: ParamEnv < ' tcx > ,
384+ region_context : DefId ,
385+ o : & PredicateObligation < ' tcx > ,
386+ ) -> bool {
363387 let tcx = infcx. tcx ;
364- o. flip_polarity ( tcx)
365- . map ( |o| {
366- let mut fulfillment_cx = FulfillmentContext :: new ( ) ;
367- fulfillment_cx. register_predicate_obligation ( infcx, o) ;
368-
369- let errors = fulfillment_cx. select_all_or_error ( infcx) ;
370- if !errors. is_empty ( ) {
371- return false ;
372- }
373388
374- let mut outlives_env = OutlivesEnvironment :: new ( param_env) ;
375- // FIXME -- add "assumed to be well formed" types into the `outlives_env`
389+ let Some ( o) = o. flip_polarity ( tcx) else {
390+ return false ;
391+ } ;
376392
377- // "Save" the accumulated implied bounds into the outlives environment
378- // (due to the FIXME above, there aren't any, but this step is still needed).
379- // The "body id" is given as `CRATE_HIR_ID`, which is the same body-id used
380- // by the "dummy" causes elsewhere (body-id is only relevant when checking
381- // function bodies with closures).
382- outlives_env. save_implied_bounds ( CRATE_HIR_ID ) ;
393+ let mut fulfillment_cx = FulfillmentContext :: new ( ) ;
394+ fulfillment_cx. register_predicate_obligation ( infcx, o) ;
383395
384- infcx. process_registered_region_obligations (
385- outlives_env. region_bound_pairs_map ( ) ,
386- Some ( tcx. lifetimes . re_root_empty ) ,
387- param_env,
388- ) ;
396+ let errors = fulfillment_cx. select_all_or_error ( infcx) ;
389397
390- let errors =
391- infcx. resolve_regions ( region_context, & outlives_env, RegionckMode :: default ( ) ) ;
392- if !errors. is_empty ( ) {
393- return false ;
394- }
398+ if !errors. is_empty ( ) {
399+ return false ;
400+ }
395401
396- true
397- } )
398- . unwrap_or ( false )
402+ let mut outlives_env = OutlivesEnvironment :: new ( param_env) ;
403+ // FIXME -- add "assumed to be well formed" types into the `outlives_env`
404+
405+ // "Save" the accumulated implied bounds into the outlives environment
406+ // (due to the FIXME above, there aren't any, but this step is still needed).
407+ // The "body id" is given as `CRATE_HIR_ID`, which is the same body-id used
408+ // by the "dummy" causes elsewhere (body-id is only relevant when checking
409+ // function bodies with closures).
410+ outlives_env. save_implied_bounds ( CRATE_HIR_ID ) ;
411+
412+ infcx. process_registered_region_obligations (
413+ outlives_env. region_bound_pairs_map ( ) ,
414+ Some ( tcx. lifetimes . re_root_empty ) ,
415+ param_env,
416+ ) ;
417+
418+ let errors = infcx. resolve_regions ( region_context, & outlives_env, RegionckMode :: default ( ) ) ;
419+
420+ if !errors. is_empty ( ) {
421+ return false ;
422+ }
423+
424+ true
399425}
400426
401427pub fn trait_ref_is_knowable < ' tcx > (
0 commit comments