@@ -9,7 +9,6 @@ use crate::infer::InferOk;
9
9
use crate::solve::inspect;
10
10
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
11
11
use crate::traits::engine::TraitEngineExt;
12
- use crate::traits::outlives_bounds::InferCtxtExt as _;
13
12
use crate::traits::query::evaluate_obligation::InferCtxtExt;
14
13
use crate::traits::select::{IntercrateAmbiguityCause, TreatInductiveCycleAs};
15
14
use crate::traits::structural_normalize::StructurallyNormalizeExt;
@@ -21,7 +20,7 @@ use crate::traits::{
21
20
};
22
21
use rustc_data_structures::fx::FxIndexSet;
23
22
use rustc_errors::Diagnostic;
24
- use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
23
+ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
25
24
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
26
25
use rustc_infer::traits::{util, TraitEngine};
27
26
use rustc_middle::traits::query::NoSolution;
@@ -36,7 +35,6 @@ use rustc_session::lint::builtin::COINDUCTIVE_OVERLAP_IN_COHERENCE;
36
35
use rustc_span::symbol::sym;
37
36
use rustc_span::DUMMY_SP;
38
37
use std::fmt::Debug;
39
- use std::iter;
40
38
use std::ops::ControlFlow;
41
39
42
40
/// Whether we do the orphan check relative to this crate or
@@ -417,41 +415,8 @@ fn impl_intersection_has_negative_obligation(
417
415
418
416
plug_infer_with_placeholders(infcx, universe, (impl1_header.impl_args, impl2_header.impl_args));
419
417
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
- if !ocx.select_all_or_error().is_empty() {
438
- continue;
439
- }
440
-
441
- // FIXME: We could use the assumed_wf_types from both impls, I think,
442
- // if that wasn't implemented just for LocalDefId, and we'd need to do
443
- //the normalization ourselves since this is totally fallible...
444
- let outlives_env = OutlivesEnvironment::new(param_env);
445
-
446
- let errors = infcx.resolve_regions(&outlives_env);
447
- if !errors.is_empty() {
448
- continue;
449
- }
450
-
451
- return true;
452
- }
453
-
454
- false
418
+ util::elaborate(tcx, tcx.predicates_of(impl2_def_id).instantiate(tcx, impl2_header.impl_args))
419
+ .any(|(clause, _)| try_prove_negated_where_clause(infcx, clause, param_env))
455
420
}
456
421
457
422
fn plug_infer_with_placeholders<'tcx>(
@@ -566,60 +531,47 @@ fn plug_infer_with_placeholders<'tcx>(
566
531
});
567
532
}
568
533
569
- /// Try to prove that a negative impl exist for the obligation or its supertraits.
570
- ///
571
- /// If such a negative impl exists, then the obligation definitely must not hold
572
- /// due to coherence, even if it's not necessarily "knowable" in this crate. Any
573
- /// valid impl downstream would not be able to exist due to the overlapping
574
- /// negative impl.
575
- #[instrument(level = "debug", skip(infcx))]
576
- fn negative_impl_exists<'tcx>(
577
- infcx: &InferCtxt<'tcx>,
578
- o: &PredicateObligation<'tcx>,
579
- body_def_id: DefId,
580
- ) -> bool {
581
- // Try to prove a negative obligation exists for super predicates
582
- for pred in util::elaborate(infcx.tcx, iter::once(o.predicate)) {
583
- if prove_negated_obligation(infcx.fork(), &o.with(infcx.tcx, pred), body_def_id) {
584
- return true;
585
- }
586
- }
587
-
588
- false
589
- }
590
-
591
- #[instrument(level = "debug", skip(infcx))]
592
- fn prove_negated_obligation<'tcx>(
593
- infcx: InferCtxt<'tcx>,
594
- o: &PredicateObligation<'tcx>,
595
- body_def_id: DefId,
534
+ fn try_prove_negated_where_clause<'tcx>(
535
+ root_infcx: &InferCtxt<'tcx>,
536
+ clause: ty::Clause<'tcx>,
537
+ param_env: ty::ParamEnv<'tcx>,
596
538
) -> bool {
597
- let tcx = infcx.tcx;
598
-
599
- let Some(o) = o.flip_polarity(tcx) else {
539
+ let Some(negative_predicate) = clause.as_predicate().flip_polarity(root_infcx.tcx) else {
600
540
return false;
601
541
};
602
542
603
- let param_env = o.param_env;
604
- let ocx = ObligationCtxt::new(&infcx);
605
- ocx.register_obligation(o);
606
- let errors = ocx.select_all_or_error();
607
- if !errors.is_empty() {
543
+ // FIXME(with_negative_coherence): the infcx has region contraints from equating
544
+ // the impl headers as requirements. Given that the only region constraints we
545
+ // get are involving inference regions in the root, it shouldn't matter, but
546
+ // still sus.
547
+ //
548
+ // We probably should just throw away the region obligations registered up until
549
+ // now, or ideally use them as assumptions when proving the region obligations
550
+ // that we get from proving the negative predicate below.
551
+ let ref infcx = root_infcx.fork();
552
+ let ocx = ObligationCtxt::new(infcx);
553
+
554
+ ocx.register_obligation(Obligation::new(
555
+ infcx.tcx,
556
+ ObligationCause::dummy(),
557
+ param_env,
558
+ negative_predicate,
559
+ ));
560
+ if !ocx.select_all_or_error().is_empty() {
608
561
return false;
609
562
}
610
563
611
- let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);
564
+ // FIXME: We could use the assumed_wf_types from both impls, I think,
565
+ // if that wasn't implemented just for LocalDefId, and we'd need to do
566
+ // the normalization ourselves since this is totally fallible...
567
+ let outlives_env = OutlivesEnvironment::new(param_env);
612
568
613
- let ocx = ObligationCtxt::new(&infcx );
614
- let Ok(wf_tys) = ocx.assumed_wf_types(param_env, body_def_id) else {
569
+ let errors = infcx.resolve_regions(&outlives_env );
570
+ if !errors.is_empty() {
615
571
return false;
616
- };
572
+ }
617
573
618
- let outlives_env = OutlivesEnvironment::with_bounds(
619
- param_env,
620
- infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),
621
- );
622
- infcx.resolve_regions(&outlives_env).is_empty()
574
+ true
623
575
}
624
576
625
577
/// Returns whether all impls which would apply to the `trait_ref`
0 commit comments