Skip to content

Commit 506ec26

Browse files
Don't require intercrate mode for negative coherence
1 parent 4f3da90 commit 506ec26

9 files changed

+21
-53
lines changed

compiler/rustc_infer/src/infer/at.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,15 @@ impl<'tcx> InferCtxt<'tcx> {
6565

6666
/// Forks the inference context, creating a new inference context with the same inference
6767
/// variables in the same state. This can be used to "branch off" many tests from the same
68-
/// common state. Used in coherence.
68+
/// common state.
6969
pub fn fork(&self) -> Self {
70+
self.fork_with_intercrate(self.intercrate)
71+
}
72+
73+
/// Forks the inference context, creating a new inference context with the same inference
74+
/// variables in the same state, except possibly changing the intercrate mode. This can be
75+
/// used to "branch off" many tests from the same common state. Used in negative coherence.
76+
pub fn fork_with_intercrate(&self, intercrate: bool) -> Self {
7077
Self {
7178
tcx: self.tcx,
7279
defining_use_anchor: self.defining_use_anchor,
@@ -81,7 +88,7 @@ impl<'tcx> InferCtxt<'tcx> {
8188
tainted_by_errors: self.tainted_by_errors.clone(),
8289
err_count_on_creation: self.err_count_on_creation,
8390
universe: self.universe.clone(),
84-
intercrate: self.intercrate,
91+
intercrate,
8592
next_trait_solver: self.next_trait_solver,
8693
}
8794
}

compiler/rustc_trait_selection/src/traits/coherence.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@ fn impl_intersection_has_negative_obligation(
397397
) -> bool {
398398
debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id);
399399

400+
// N.B. We need to unify impl headers *with* intercrate mode, even if proving negative predicates
401+
// do not need intercrate mode enabled.
400402
let ref infcx = tcx.infer_ctxt().intercrate(true).with_next_trait_solver(true).build();
401403
let universe = infcx.universe();
402404

@@ -549,7 +551,12 @@ fn try_prove_negated_where_clause<'tcx>(
549551
// We probably should just throw away the region obligations registered up until
550552
// now, or ideally use them as assumptions when proving the region obligations
551553
// that we get from proving the negative predicate below.
552-
let ref infcx = root_infcx.fork();
554+
//
555+
// N.B. We don't need to use intercrate mode here because we're trying to prove
556+
// the *existence* of a negative goal, not the non-existence of a positive goal.
557+
// Without this, we over-eagerly register coherence ambiguity candidates when
558+
// impl candidates do exist.
559+
let ref infcx = root_infcx.fork_with_intercrate(false);
553560
let ocx = ObligationCtxt::new(infcx);
554561

555562
ocx.register_obligation(Obligation::new(

tests/ui/coherence/coherence-negative-outlives-lifetimes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// revisions: stock with_negative_coherence
2-
//[with_negative_coherence] known-bug: unknown
2+
//[with_negative_coherence] check-pass
33

44
#![feature(negative_impls)]
55
#![cfg_attr(with_negative_coherence, feature(with_negative_coherence))]

tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr

-11
This file was deleted.

tests/ui/coherence/coherence-overlap-with-regions.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
// known-bug: unknown
2-
3-
// This fails because we currently perform negative coherence in coherence mode.
4-
// This means that when looking for a negative predicate, we also assemble a
5-
// coherence-unknowable predicate. Since confirming the negative impl has region
6-
// obligations, we don't prefer the impl over the unknowable predicate
7-
// unconditionally and instead flounder.
1+
// check-pass
82

93
#![feature(negative_impls)]
104
#![feature(rustc_attrs)]

tests/ui/coherence/coherence-overlap-with-regions.stderr

-11
This file was deleted.

tests/ui/coherence/negative-coherence-considering-regions.any_lt.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0119]: conflicting implementations of trait `Bar` for type `&_`
2-
--> $DIR/negative-coherence-considering-regions.rs:22:1
2+
--> $DIR/negative-coherence-considering-regions.rs:16:1
33
|
44
LL | impl<T> Bar for T where T: Foo {}
55
| ------------------------------ first implementation here

tests/ui/coherence/negative-coherence-considering-regions.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
// revisions: any_lt static_lt
2-
//[static_lt] known-bug: unknown
3-
4-
// This fails because we currently perform negative coherence in coherence mode.
5-
// This means that when looking for a negative predicate, we also assemble a
6-
// coherence-unknowable predicate. Since confirming the negative impl has region
7-
// obligations, we don't prefer the impl over the unknowable predicate
8-
// unconditionally and instead flounder.
2+
//[static_lt] check-pass
93

104
#![feature(negative_impls)]
115
#![feature(with_negative_coherence)]

tests/ui/coherence/negative-coherence-considering-regions.static_lt.stderr

-12
This file was deleted.

0 commit comments

Comments
 (0)