@@ -17,8 +17,8 @@ use crate::traits::{
17
17
use rustc_errors:: Diagnostic ;
18
18
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
19
19
use 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 } ;
22
22
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 ;
@@ -353,49 +353,75 @@ fn negative_impl<'cx, 'tcx>(
353
353
} )
354
354
}
355
355
356
+ /// Try to prove that a negative impl exist for the given obligation and their super predicates.
357
+ #[ instrument( level = "debug" , skip( selcx) ) ]
356
358
fn negative_impl_exists < ' cx , ' tcx > (
357
359
selcx : & SelectionContext < ' cx , ' tcx > ,
358
360
param_env : ty:: ParamEnv < ' tcx > ,
359
361
region_context : DefId ,
360
362
o : & PredicateObligation < ' tcx > ,
361
363
) -> bool {
362
364
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 {
363
387
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
- }
373
388
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
+ } ;
376
392
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) ;
383
395
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) ;
389
397
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
+ }
395
401
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
399
425
}
400
426
401
427
pub fn trait_ref_is_knowable < ' tcx > (
0 commit comments