diff options
| author | Santiago Pastorino <spastorino@gmail.com> | 2022-03-17 11:26:45 -0300 |
|---|---|---|
| committer | Santiago Pastorino <spastorino@gmail.com> | 2022-03-17 12:15:11 -0300 |
| commit | 64dfd3b2340a42f5fda5802d50c9739d38533102 (patch) | |
| tree | af400c4c1e7bb7983e39dfbc999c7e9f2ad07d55 | |
| parent | 78346489c66779d024c60af2d2f0f5d9d455f688 (diff) | |
| download | rust-64dfd3b2340a42f5fda5802d50c9739d38533102.tar.gz rust-64dfd3b2340a42f5fda5802d50c9739d38533102.zip | |
Make negative coherence work when there's impl negative on super predicates
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/coherence.rs | 24 | ||||
| -rw-r--r-- | src/test/ui/coherence/coherence-overlap-super-negative.rs | 18 |
2 files changed, 34 insertions, 8 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index a3d32acc6fb..72a06abd8e0 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -18,7 +18,7 @@ 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::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,6 +353,7 @@ fn negative_impl<'cx, 'tcx>( }) } +#[instrument(level = "debug", skip(selcx))] fn negative_impl_exists<'cx, 'tcx>( selcx: &SelectionContext<'cx, 'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -361,14 +362,18 @@ fn negative_impl_exists<'cx, 'tcx>( ) -> bool { let infcx = &selcx.infcx().fork(); let tcx = infcx.tcx; - o.flip_polarity(tcx) - .map(|o| { + + let super_obligations = util::elaborate_predicates(tcx, iter::once(o.predicate)); + + for o in iter::once(o.clone()).chain(super_obligations) { + if let Some(o) = o.flip_polarity(tcx) { 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; + continue; } let mut outlives_env = OutlivesEnvironment::new(param_env); @@ -389,13 +394,16 @@ fn negative_impl_exists<'cx, 'tcx>( let errors = infcx.resolve_regions(region_context, &outlives_env, RegionckMode::default()); + if !errors.is_empty() { - return false; + continue; } - true - }) - .unwrap_or(false) + return true; + } + } + + false } pub fn trait_ref_is_knowable<'tcx>( diff --git a/src/test/ui/coherence/coherence-overlap-super-negative.rs b/src/test/ui/coherence/coherence-overlap-super-negative.rs new file mode 100644 index 00000000000..d296a094a37 --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-super-negative.rs @@ -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() {} |
