Add rustc_strict_coherence attribute and use it to check overlap
This commit is contained in:
parent
74454c4888
commit
da79fa964c
@ -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)),
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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<T: AB> 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() {}
|
@ -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<T: AB> 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`.
|
18
src/test/ui/coherence/coherence-overlap-negate-strict.rs
Normal file
18
src/test/ui/coherence/coherence-overlap-negate-strict.rs
Normal file
@ -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<T: A + B> C for T {}
|
||||
#[rustc_strict_coherence]
|
||||
impl C for u32 {}
|
||||
|
||||
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user