@@ -13,11 +13,10 @@ use crate::traits::outlives_bounds::InferCtxtExt as _;
13
13
use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt ;
14
14
use crate :: traits:: select:: { IntercrateAmbiguityCause , TreatInductiveCycleAs } ;
15
15
use crate :: traits:: structural_normalize:: StructurallyNormalizeExt ;
16
- use crate :: traits:: util:: impl_subject_and_oblig;
17
16
use crate :: traits:: NormalizeExt ;
18
17
use crate :: traits:: SkipLeakCheck ;
19
18
use crate :: traits:: {
20
- self , Obligation , ObligationCause , ObligationCtxt , PredicateObligation , PredicateObligations ,
19
+ Obligation , ObligationCause , ObligationCtxt , PredicateObligation , PredicateObligations ,
21
20
SelectionContext ,
22
21
} ;
23
22
use rustc_data_structures:: fx:: FxIndexSet ;
@@ -32,7 +31,7 @@ use rustc_middle::traits::DefiningAnchor;
32
31
use rustc_middle:: ty:: fast_reject:: { DeepRejectCtxt , TreatParams } ;
33
32
use rustc_middle:: ty:: print:: with_no_trimmed_paths;
34
33
use rustc_middle:: ty:: visit:: { TypeVisitable , TypeVisitableExt } ;
35
- use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeVisitor } ;
34
+ use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitor } ;
36
35
use rustc_session:: lint:: builtin:: COINDUCTIVE_OVERLAP_IN_COHERENCE ;
37
36
use rustc_span:: symbol:: sym;
38
37
use rustc_span:: DUMMY_SP ;
@@ -399,53 +398,167 @@ fn impl_intersection_has_negative_obligation(
399
398
) -> bool {
400
399
debug ! ( "negative_impl(impl1_def_id={:?}, impl2_def_id={:?})" , impl1_def_id, impl2_def_id) ;
401
400
402
- // Create an infcx, taking the predicates of impl1 as assumptions:
403
- let infcx = tcx. infer_ctxt ( ) . build ( ) ;
404
- // create a parameter environment corresponding to a (placeholder) instantiation of impl1
405
- let impl_env = tcx. param_env ( impl1_def_id) ;
406
- let subject1 = match traits:: fully_normalize (
407
- & infcx,
408
- ObligationCause :: dummy ( ) ,
409
- impl_env,
410
- tcx. impl_subject ( impl1_def_id) . instantiate_identity ( ) ,
411
- ) {
412
- Ok ( s) => s,
413
- Err ( err) => {
414
- tcx. sess . delay_span_bug (
415
- tcx. def_span ( impl1_def_id) ,
416
- format ! ( "failed to fully normalize {impl1_def_id:?}: {err:?}" ) ,
417
- ) ;
418
- return false ;
419
- }
420
- } ;
401
+ let ref infcx = tcx. infer_ctxt ( ) . intercrate ( true ) . build ( ) ;
402
+ let universe = infcx. create_next_universe ( ) ;
421
403
422
- // Attempt to prove that impl2 applies, given all of the above.
423
- let selcx = & mut SelectionContext :: new ( & infcx) ;
424
- let impl2_args = infcx. fresh_args_for_item ( DUMMY_SP , impl2_def_id) ;
425
- let ( subject2, normalization_obligations) =
426
- impl_subject_and_oblig ( selcx, impl_env, impl2_def_id, impl2_args, |_, _| {
427
- ObligationCause :: dummy ( )
428
- } ) ;
429
-
430
- // do the impls unify? If not, then it's not currently possible to prove any
431
- // obligations about their intersection.
432
- let Ok ( InferOk { obligations : equate_obligations, .. } ) =
433
- infcx. at ( & ObligationCause :: dummy ( ) , impl_env) . eq ( DefineOpaqueTypes :: No , subject1, subject2)
404
+ let impl1_header = fresh_impl_header ( infcx, impl1_def_id) ;
405
+ let param_env =
406
+ ty:: EarlyBinder :: bind ( tcx. param_env ( impl1_def_id) ) . instantiate ( tcx, impl1_header. impl_args ) ;
407
+
408
+ let impl2_header = fresh_impl_header ( infcx, impl2_def_id) ;
409
+
410
+ // Equate the headers to find their intersection (the general type, with infer vars,
411
+ // that may apply both impls).
412
+ let Some ( _equate_obligations) =
413
+ equate_impl_headers ( infcx, param_env, & impl1_header, & impl2_header)
434
414
else {
435
- debug ! ( "explicit_disjoint: {:?} does not unify with {:?}" , subject1, subject2) ;
436
415
return false ;
437
416
} ;
438
417
439
- for obligation in normalization_obligations. into_iter ( ) . chain ( equate_obligations) {
440
- if negative_impl_exists ( & infcx, & obligation, impl1_def_id) {
441
- debug ! ( "overlap: obligation unsatisfiable {:?}" , obligation) ;
442
- return true ;
418
+ plug_infer_with_placeholders ( infcx, universe, ( impl1_header. impl_args , impl2_header. impl_args ) ) ;
419
+
420
+ for ( predicate, _) in util:: elaborate (
421
+ tcx,
422
+ tcx. predicates_of ( impl2_def_id) . instantiate ( tcx, impl2_header. impl_args ) ,
423
+ ) {
424
+ let Some ( negative_predicate) = predicate. as_predicate ( ) . flip_polarity ( tcx) else {
425
+ continue ;
426
+ } ;
427
+
428
+ let ref infcx = infcx. fork ( ) ;
429
+ let ocx = ObligationCtxt :: new ( infcx) ;
430
+
431
+ ocx. register_obligation ( Obligation :: new (
432
+ tcx,
433
+ ObligationCause :: dummy ( ) ,
434
+ param_env,
435
+ negative_predicate,
436
+ ) ) ;
437
+
438
+ if !ocx. select_all_or_error ( ) . is_empty ( ) {
439
+ continue ;
443
440
}
441
+
442
+ // FIXME: regions here too...
443
+
444
+ return true ;
444
445
}
445
446
446
447
false
447
448
}
448
449
450
+ fn plug_infer_with_placeholders < ' tcx > (
451
+ infcx : & InferCtxt < ' tcx > ,
452
+ universe : ty:: UniverseIndex ,
453
+ value : impl TypeVisitable < TyCtxt < ' tcx > > ,
454
+ ) {
455
+ struct PlugInferWithPlaceholder < ' a , ' tcx > {
456
+ infcx : & ' a InferCtxt < ' tcx > ,
457
+ universe : ty:: UniverseIndex ,
458
+ var : ty:: BoundVar ,
459
+ }
460
+
461
+ impl < ' tcx > PlugInferWithPlaceholder < ' _ , ' tcx > {
462
+ fn next_var ( & mut self ) -> ty:: BoundVar {
463
+ let var = self . var ;
464
+ self . var = self . var + 1 ;
465
+ var
466
+ }
467
+ }
468
+
469
+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for PlugInferWithPlaceholder < ' _ , ' tcx > {
470
+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
471
+ let ty = self . infcx . shallow_resolve ( ty) ;
472
+ if ty. is_ty_var ( ) {
473
+ let Ok ( InferOk { value : ( ) , obligations } ) =
474
+ self . infcx . at ( & ObligationCause :: dummy ( ) , ty:: ParamEnv :: empty ( ) ) . eq (
475
+ DefineOpaqueTypes :: No ,
476
+ ty,
477
+ Ty :: new_placeholder (
478
+ self . infcx . tcx ,
479
+ ty:: Placeholder {
480
+ universe : self . universe ,
481
+ bound : ty:: BoundTy {
482
+ var : self . next_var ( ) ,
483
+ kind : ty:: BoundTyKind :: Anon ,
484
+ } ,
485
+ } ,
486
+ ) ,
487
+ )
488
+ else {
489
+ bug ! ( )
490
+ } ;
491
+ assert_eq ! ( obligations, & [ ] ) ;
492
+ ControlFlow :: Continue ( ( ) )
493
+ } else {
494
+ ty. super_visit_with ( self )
495
+ }
496
+ }
497
+
498
+ fn visit_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
499
+ let ct = self . infcx . shallow_resolve ( ct) ;
500
+ if ct. is_ct_infer ( ) {
501
+ let Ok ( InferOk { value : ( ) , obligations } ) =
502
+ self . infcx . at ( & ObligationCause :: dummy ( ) , ty:: ParamEnv :: empty ( ) ) . eq (
503
+ DefineOpaqueTypes :: No ,
504
+ ct,
505
+ ty:: Const :: new_placeholder (
506
+ self . infcx . tcx ,
507
+ ty:: Placeholder { universe : self . universe , bound : self . next_var ( ) } ,
508
+ ct. ty ( ) ,
509
+ ) ,
510
+ )
511
+ else {
512
+ bug ! ( )
513
+ } ;
514
+ assert_eq ! ( obligations, & [ ] ) ;
515
+ ControlFlow :: Continue ( ( ) )
516
+ } else {
517
+ ct. super_visit_with ( self )
518
+ }
519
+ }
520
+
521
+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
522
+ if let ty:: ReVar ( vid) = * r {
523
+ let r = self
524
+ . infcx
525
+ . inner
526
+ . borrow_mut ( )
527
+ . unwrap_region_constraints ( )
528
+ . opportunistic_resolve_var ( self . infcx . tcx , vid) ;
529
+ if r. is_var ( ) {
530
+ let Ok ( InferOk { value : ( ) , obligations } ) =
531
+ self . infcx . at ( & ObligationCause :: dummy ( ) , ty:: ParamEnv :: empty ( ) ) . eq (
532
+ DefineOpaqueTypes :: No ,
533
+ r,
534
+ ty:: Region :: new_placeholder (
535
+ self . infcx . tcx ,
536
+ ty:: Placeholder {
537
+ universe : self . universe ,
538
+ bound : ty:: BoundRegion {
539
+ var : self . next_var ( ) ,
540
+ kind : ty:: BoundRegionKind :: BrAnon ,
541
+ } ,
542
+ } ,
543
+ ) ,
544
+ )
545
+ else {
546
+ bug ! ( )
547
+ } ;
548
+ assert_eq ! ( obligations, & [ ] ) ;
549
+ }
550
+ }
551
+ ControlFlow :: Continue ( ( ) )
552
+ }
553
+ }
554
+
555
+ value. visit_with ( & mut PlugInferWithPlaceholder {
556
+ infcx,
557
+ universe,
558
+ var : ty:: BoundVar :: from_u32 ( 0 ) ,
559
+ } ) ;
560
+ }
561
+
449
562
/// Try to prove that a negative impl exist for the obligation or its supertraits.
450
563
///
451
564
/// If such a negative impl exists, then the obligation definitely must not hold
0 commit comments