From ba7272959df7447c7393a14f475663de1f250f8f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 20 Aug 2022 03:23:23 +0000 Subject: [PATCH] Use separate infcx to solve obligations during negative coherence --- .../src/traits/coherence.rs | 21 +++++++------------ .../coherence-negative-outlives-lifetimes.rs | 7 ++++++- ...-negative-outlives-lifetimes.stock.stderr} | 2 +- ...s-lifetimes.with_negative_coherence.stderr | 11 ++++++++++ 4 files changed, 26 insertions(+), 15 deletions(-) rename src/test/ui/coherence/{coherence-negative-outlives-lifetimes.stderr => coherence-negative-outlives-lifetimes.stock.stderr} (88%) create mode 100644 src/test/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 985600d9ebc..3bc08fba91a 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -342,10 +342,8 @@ fn equate<'cx, 'tcx>( }; let selcx = &mut SelectionContext::new(&infcx); - let opt_failing_obligation = obligations - .into_iter() - .chain(more_obligations) - .find(|o| negative_impl_exists(selcx, impl_env, o)); + let opt_failing_obligation = + obligations.into_iter().chain(more_obligations).find(|o| negative_impl_exists(selcx, o)); if let Some(failing_obligation) = opt_failing_obligation { debug!("overlap: obligation unsatisfiable {:?}", failing_obligation); @@ -359,18 +357,15 @@ fn equate<'cx, 'tcx>( #[instrument(level = "debug", skip(selcx))] fn negative_impl_exists<'cx, 'tcx>( selcx: &SelectionContext<'cx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, o: &PredicateObligation<'tcx>, ) -> bool { - let infcx = &selcx.infcx().fork(); - - if resolve_negative_obligation(infcx, param_env, o) { + if resolve_negative_obligation(selcx.infcx().fork(), o) { return true; } // Try to prove a negative obligation exists for super predicates - for o in util::elaborate_predicates(infcx.tcx, iter::once(o.predicate)) { - if resolve_negative_obligation(infcx, param_env, &o) { + for o in util::elaborate_predicates(selcx.tcx(), iter::once(o.predicate)) { + if resolve_negative_obligation(selcx.infcx().fork(), &o) { return true; } } @@ -380,8 +375,7 @@ fn negative_impl_exists<'cx, 'tcx>( #[instrument(level = "debug", skip(infcx))] fn resolve_negative_obligation<'cx, 'tcx>( - infcx: &InferCtxt<'cx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, + infcx: InferCtxt<'cx, 'tcx>, o: &PredicateObligation<'tcx>, ) -> bool { let tcx = infcx.tcx; @@ -390,7 +384,8 @@ fn resolve_negative_obligation<'cx, 'tcx>( return false; }; - let errors = super::fully_solve_obligation(infcx, o); + let param_env = o.param_env; + let errors = super::fully_solve_obligation(&infcx, o); if !errors.is_empty() { return false; } diff --git a/src/test/ui/coherence/coherence-negative-outlives-lifetimes.rs b/src/test/ui/coherence/coherence-negative-outlives-lifetimes.rs index 159788b1b77..221c1bc23b3 100644 --- a/src/test/ui/coherence/coherence-negative-outlives-lifetimes.rs +++ b/src/test/ui/coherence/coherence-negative-outlives-lifetimes.rs @@ -1,10 +1,15 @@ +// revisions: stock with_negative_coherence #![feature(negative_impls)] +#![cfg_attr(with_negative_coherence, feature(with_negative_coherence))] // FIXME: this should compile trait MyPredicate<'a> {} -impl<'a, T> !MyPredicate<'a> for &T where T: 'a {} + +impl<'a, T> !MyPredicate<'a> for &'a T where T: 'a {} + trait MyTrait<'a> {} + impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} impl<'a, T> MyTrait<'a> for &'a T {} //~^ ERROR: conflicting implementations of trait `MyTrait<'_>` for type `&_` diff --git a/src/test/ui/coherence/coherence-negative-outlives-lifetimes.stderr b/src/test/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr similarity index 88% rename from src/test/ui/coherence/coherence-negative-outlives-lifetimes.stderr rename to src/test/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr index 263bd19b424..097cc4e0fe3 100644 --- a/src/test/ui/coherence/coherence-negative-outlives-lifetimes.stderr +++ b/src/test/ui/coherence/coherence-negative-outlives-lifetimes.stock.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `MyTrait<'_>` for type `&_` - --> $DIR/coherence-negative-outlives-lifetimes.rs:9:1 + --> $DIR/coherence-negative-outlives-lifetimes.rs:14:1 | LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} | ---------------------------------------------- first implementation here diff --git a/src/test/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr b/src/test/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr new file mode 100644 index 00000000000..097cc4e0fe3 --- /dev/null +++ b/src/test/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `MyTrait<'_>` for type `&_` + --> $DIR/coherence-negative-outlives-lifetimes.rs:14:1 + | +LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} + | ---------------------------------------------- first implementation here +LL | impl<'a, T> MyTrait<'a> for &'a T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`.