Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 15.5k
Make negative coherence work when there's impl negative on super predicates#95039
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
c3797dc783464864dfd3b61a05ef91846fe9c076f3ba8b4a489a00ccFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -17,8 +17,8 @@ use crate::traits::{ | ||
| use rustc_errors::Diagnostic; | ||
| use rustc_hir::def_id::{DefId, LOCAL_CRATE}; | ||
| use rustc_hir::CRATE_HIR_ID; | ||
| use rustc_infer::infer::TyCtxtInferExt; | ||
| use rustc_infer::traits::TraitEngine; | ||
| use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; | ||
| use rustc_infer::traits::{util, TraitEngine}; | ||
| use rustc_middle::traits::specialization_graph::OverlapMode; | ||
| use rustc_middle::ty::fast_reject::{self, TreatParams}; | ||
| use rustc_middle::ty::fold::TypeFoldable; | ||
| @@ -353,49 +353,75 @@ fn negative_impl<'cx, 'tcx>( | ||
| }) | ||
| } | ||
| /// Try to prove that a negative impl exist for the given obligation and their super predicates. | ||
| #[instrument(level = "debug", skip(selcx))] | ||
| fn negative_impl_exists<'cx, 'tcx>( | ||
| selcx: &SelectionContext<'cx, 'tcx>, | ||
| param_env: ty::ParamEnv<'tcx>, | ||
| region_context: DefId, | ||
| o: &PredicateObligation<'tcx>, | ||
| ) -> bool { | ||
| let infcx = &selcx.infcx().fork(); | ||
| if resolve_negative_obligation(infcx, param_env, region_context, o) { | ||
| return true; | ||
| } | ||
| // Try to prove a negative obligation exist for super predicates | ||
spastorino marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| for o in util::elaborate_predicates(infcx.tcx, iter::once(o.predicate)) { | ||
| if resolve_negative_obligation(infcx, param_env, region_context, &o) { | ||
| return true; | ||
| } | ||
| } | ||
| false | ||
| } | ||
| #[instrument(level = "debug", skip(infcx))] | ||
| fn resolve_negative_obligation<'cx, 'tcx>( | ||
| infcx: &InferCtxt<'cx, 'tcx>, | ||
| param_env: ty::ParamEnv<'tcx>, | ||
| region_context: DefId, | ||
| o: &PredicateObligation<'tcx>, | ||
| ) -> bool { | ||
| let tcx = infcx.tcx; | ||
| o.flip_polarity(tcx) | ||
| .map(|o| { | ||
| let mut fulfillment_cx = FulfillmentContext::new(); | ||
| fulfillment_cx.register_predicate_obligation(infcx, o); | ||
| let errors = fulfillment_cx.select_all_or_error(infcx); | ||
| if !errors.is_empty() { | ||
| return false; | ||
| } | ||
| let mut outlives_env = OutlivesEnvironment::new(param_env); | ||
| // FIXME -- add "assumed to be well formed" types into the `outlives_env` | ||
| let Some(o) = o.flip_polarity(tcx) else { | ||
| return false; | ||
| }; | ||
| // "Save" the accumulated implied bounds into the outlives environment | ||
| // (due to the FIXME above, there aren't any, but this step is still needed). | ||
| // The "body id" is given as `CRATE_HIR_ID`, which is the same body-id used | ||
| // by the "dummy" causes elsewhere (body-id is only relevant when checking | ||
| // function bodies with closures). | ||
| outlives_env.save_implied_bounds(CRATE_HIR_ID); | ||
| let mut fulfillment_cx = FulfillmentContext::new(); | ||
| fulfillment_cx.register_predicate_obligation(infcx, o); | ||
| infcx.process_registered_region_obligations( | ||
| outlives_env.region_bound_pairs_map(), | ||
| Some(tcx.lifetimes.re_root_empty), | ||
| param_env, | ||
| ); | ||
| let errors = fulfillment_cx.select_all_or_error(infcx); | ||
| let errors = | ||
| infcx.resolve_regions(region_context, &outlives_env, RegionckMode::default()); | ||
| if !errors.is_empty() { | ||
| return false; | ||
| } | ||
| if !errors.is_empty() { | ||
| return false; | ||
| } | ||
| true | ||
| }) | ||
| .unwrap_or(false) | ||
| let mut outlives_env = OutlivesEnvironment::new(param_env); | ||
| // FIXME -- add "assumed to be well formed" types into the `outlives_env` | ||
| // "Save" the accumulated implied bounds into the outlives environment | ||
| // (due to the FIXME above, there aren't any, but this step is still needed). | ||
| // The "body id" is given as `CRATE_HIR_ID`, which is the same body-id used | ||
| // by the "dummy" causes elsewhere (body-id is only relevant when checking | ||
| // function bodies with closures). | ||
| outlives_env.save_implied_bounds(CRATE_HIR_ID); | ||
| infcx.process_registered_region_obligations( | ||
| outlives_env.region_bound_pairs_map(), | ||
| Some(tcx.lifetimes.re_root_empty), | ||
| param_env, | ||
| ); | ||
| let errors = infcx.resolve_regions(region_context, &outlives_env, RegionckMode::default()); | ||
| if !errors.is_empty() { | ||
| return false; | ||
| } | ||
| true | ||
| } | ||
| pub fn trait_ref_is_knowable<'tcx>( | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // check-pass | ||
| #![feature(negative_impls)] | ||
| #![feature(with_negative_coherence)] | ||
| trait A {} | ||
| trait B: A {} | ||
| impl !A for u32 {} | ||
| impl !B for u32 {} | ||
| fn main() {} |
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // check-pass | ||
| #![feature(negative_impls)] | ||
| #![feature(rustc_attrs)] | ||
| #![feature(with_negative_coherence)] | ||
| trait Trait1: Trait2 {} | ||
| trait Trait2 {} | ||
| struct MyType {} | ||
| impl !Trait2 for MyType {} | ||
| #[rustc_strict_coherence] | ||
| trait Foo {} | ||
| impl<T: Trait1> Foo for T {} | ||
| impl Foo for MyType {} | ||
| fn main() {} |
Uh oh!
There was an error while loading. Please reload this page.