From d688b86c3df18c76de65966d5355e19a7df5deb4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 16 Nov 2023 22:50:59 +0000 Subject: [PATCH] Ignore but do not assume region obligations from unifying headers in negative coherence --- .../src/traits/coherence.rs | 12 ++++----- ...constraints-on-unification.explicit.stderr | 19 ++++++++++++++ ...older-region-constraints-on-unification.rs | 25 +++++++++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr create mode 100644 tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 7ca33ae41c0ce..faded18582f70 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -542,14 +542,14 @@ fn try_prove_negated_where_clause<'tcx>( }; // FIXME(with_negative_coherence): the infcx has region contraints from equating - // the impl headers as requirements. Given that the only region constraints we - // get are involving inference regions in the root, it shouldn't matter, but - // still sus. + // the impl headers as requirements. // - // We probably should just throw away the region obligations registered up until - // now, or ideally use them as assumptions when proving the region obligations - // that we get from proving the negative predicate below. + // We ideally should use these region constraints as assumptions when proving + // the region obligations that we get from proving the negative predicate below. let ref infcx = root_infcx.fork(); + let _ = infcx.take_registered_region_obligations(); + let _ = infcx.take_and_reset_region_constraints(); + let ocx = ObligationCtxt::new(infcx); ocx.register_obligation(Obligation::new( diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr new file mode 100644 index 0000000000000..34f3904443c31 --- /dev/null +++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr @@ -0,0 +1,19 @@ +error: conflicting implementations of trait `FnMarker` for type `fn(&_)` + --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:21:1 + | +LL | impl FnMarker for fn(T) {} + | ------------------------------------------- first implementation here +LL | impl FnMarker for fn(&T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&_)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details +note: the lint level is defined here + --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:4:11 + | +LL | #![forbid(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs new file mode 100644 index 0000000000000..26d9d84d8f0c9 --- /dev/null +++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs @@ -0,0 +1,25 @@ +// revisions: explicit implicit +//[implicit] check-pass + +#![forbid(coherence_leak_check)] +#![feature(negative_impls, with_negative_coherence)] + +pub trait Marker {} + +#[cfg(implicit)] +impl !Marker for &T {} + +#[cfg(explicit)] +impl<'a, T: ?Sized + 'a> !Marker for &'a T {} + +trait FnMarker {} + +// Unifying these two impls below results in a `T: '!0` obligation +// that we shouldn't need to care about. Ideally, we'd treat that +// as an assumption when proving `&'!0 T: Marker`... +impl FnMarker for fn(T) {} +impl FnMarker for fn(&T) {} +//[explicit]~^ ERROR conflicting implementations of trait `FnMarker` for type `fn(&_)` +//[explicit]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +fn main() {}