Skip to content

Commit 64dfd3b

Browse files
committed
Make negative coherence work when there's impl negative on super predicates
1 parent 7834648 commit 64dfd3b

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_errors::Diagnostic;
1818
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
1919
use rustc_hir::CRATE_HIR_ID;
2020
use rustc_infer::infer::TyCtxtInferExt;
21-
use rustc_infer::traits::TraitEngine;
21+
use rustc_infer::traits::{util, TraitEngine};
2222
use rustc_middle::traits::specialization_graph::OverlapMode;
2323
use rustc_middle::ty::fast_reject::{self, TreatParams};
2424
use rustc_middle::ty::fold::TypeFoldable;
@@ -353,6 +353,7 @@ fn negative_impl<'cx, 'tcx>(
353353
})
354354
}
355355

356+
#[instrument(level = "debug", skip(selcx))]
356357
fn negative_impl_exists<'cx, 'tcx>(
357358
selcx: &SelectionContext<'cx, 'tcx>,
358359
param_env: ty::ParamEnv<'tcx>,
@@ -361,14 +362,18 @@ fn negative_impl_exists<'cx, 'tcx>(
361362
) -> bool {
362363
let infcx = &selcx.infcx().fork();
363364
let tcx = infcx.tcx;
364-
o.flip_polarity(tcx)
365-
.map(|o| {
365+
366+
let super_obligations = util::elaborate_predicates(tcx, iter::once(o.predicate));
367+
368+
for o in iter::once(o.clone()).chain(super_obligations) {
369+
if let Some(o) = o.flip_polarity(tcx) {
366370
let mut fulfillment_cx = FulfillmentContext::new();
367371
fulfillment_cx.register_predicate_obligation(infcx, o);
368372

369373
let errors = fulfillment_cx.select_all_or_error(infcx);
374+
370375
if !errors.is_empty() {
371-
return false;
376+
continue;
372377
}
373378

374379
let mut outlives_env = OutlivesEnvironment::new(param_env);
@@ -389,13 +394,16 @@ fn negative_impl_exists<'cx, 'tcx>(
389394

390395
let errors =
391396
infcx.resolve_regions(region_context, &outlives_env, RegionckMode::default());
397+
392398
if !errors.is_empty() {
393-
return false;
399+
continue;
394400
}
395401

396-
true
397-
})
398-
.unwrap_or(false)
402+
return true;
403+
}
404+
}
405+
406+
false
399407
}
400408

401409
pub fn trait_ref_is_knowable<'tcx>(
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// check-pass
2+
3+
#![feature(negative_impls)]
4+
#![feature(rustc_attrs)]
5+
#![feature(with_negative_coherence)]
6+
7+
trait Trait1: Trait2 {}
8+
trait Trait2 {}
9+
10+
struct MyType {}
11+
impl !Trait2 for MyType {}
12+
13+
#[rustc_strict_coherence]
14+
trait Foo {}
15+
impl<T: Trait1> Foo for T {}
16+
impl Foo for MyType {}
17+
18+
fn main() {}

0 commit comments

Comments
 (0)