diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 85b0db468d125..33188d375f5d5 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -556,6 +556,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word)), rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word)), + rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word)), rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index fddb225345f49..084cd95de6003 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1142,6 +1142,7 @@ symbols! { rustc_specialization_trait, rustc_stable, rustc_std_internal_symbol, + rustc_strict_coherence, rustc_symbol_name, rustc_synthetic, rustc_test_marker, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index d422bd66b10ac..35fd31536806c 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -222,11 +222,22 @@ fn overlap_within_probe( }) .chain(obligations) .find(|o| { - !selcx.predicate_may_hold_fatal(o) - || o.flip_polarity(tcx) + // if both impl headers are set to strict coherence it means that this will be accepted + // only if it's stated that T: !Trait. So only prove that the negated obligation holds. + if tcx.has_attr(a_def_id, sym::rustc_strict_coherence) + && tcx.has_attr(b_def_id, sym::rustc_strict_coherence) + { + o.flip_polarity(tcx) .as_ref() .map(|o| selcx.infcx().predicate_must_hold_modulo_regions(o)) .unwrap_or(false) + } else { + !selcx.predicate_may_hold_fatal(o) + || o.flip_polarity(tcx) + .as_ref() + .map(|o| selcx.infcx().predicate_must_hold_modulo_regions(o)) + .unwrap_or(false) + } }); // FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported // to the canonical trait query form, `infcx.predicate_may_hold`, once diff --git a/src/test/ui/coherence/coherence-overlap-negate-alias-strict.rs b/src/test/ui/coherence/coherence-overlap-negate-alias-strict.rs new file mode 100644 index 0000000000000..16ace450b06d5 --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-negate-alias-strict.rs @@ -0,0 +1,19 @@ +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(trait_alias)] + +trait A {} +trait B {} +trait AB = A + B; + +impl !A for u32 {} + +trait C {} +#[rustc_strict_coherence] +impl C for T {} +#[rustc_strict_coherence] +impl C for u32 {} +//~^ ERROR: conflicting implementations of trait `C` for type `u32` [E0119] +// FIXME this should work, we should implement an `assemble_neg_candidates` fn + +fn main() {} diff --git a/src/test/ui/coherence/coherence-overlap-negate-alias-strict.stderr b/src/test/ui/coherence/coherence-overlap-negate-alias-strict.stderr new file mode 100644 index 0000000000000..5e436223119b9 --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-negate-alias-strict.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `C` for type `u32` + --> $DIR/coherence-overlap-negate-alias-strict.rs:15:1 + | +LL | impl C for T {} + | ------------------- first implementation here +LL | #[rustc_strict_coherence] +LL | impl C for u32 {} + | ^^^^^^^^^^^^^^ conflicting implementation for `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/coherence/coherence-overlap-negate-strict.rs b/src/test/ui/coherence/coherence-overlap-negate-strict.rs new file mode 100644 index 0000000000000..b3ae9a7bf7855 --- /dev/null +++ b/src/test/ui/coherence/coherence-overlap-negate-strict.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(negative_impls)] +#![feature(rustc_attrs)] +#![feature(trait_alias)] + +trait A {} +trait B {} + +impl !A for u32 {} + +trait C {} +#[rustc_strict_coherence] +impl C for T {} +#[rustc_strict_coherence] +impl C for u32 {} + +fn main() {}