Skip to content

Commit da79fa9

Browse files
committed
Add rustc_strict_coherence attribute and use it to check overlap
1 parent 74454c4 commit da79fa9

File tree

6 files changed

+64
-2
lines changed

6 files changed

+64
-2
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
556556
rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)),
557557
rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word)),
558558
rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word)),
559+
rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word)),
559560
rustc_attr!(TEST, rustc_variance, Normal, template!(Word)),
560561
rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")),
561562
rustc_attr!(TEST, rustc_regions, Normal, template!(Word)),

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,7 @@ symbols! {
11421142
rustc_specialization_trait,
11431143
rustc_stable,
11441144
rustc_std_internal_symbol,
1145+
rustc_strict_coherence,
11451146
rustc_symbol_name,
11461147
rustc_synthetic,
11471148
rustc_test_marker,

compiler/rustc_trait_selection/src/traits/coherence.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,22 @@ fn overlap_within_probe(
222222
})
223223
.chain(obligations)
224224
.find(|o| {
225-
!selcx.predicate_may_hold_fatal(o)
226-
|| o.flip_polarity(tcx)
225+
// if both impl headers are set to strict coherence it means that this will be accepted
226+
// only if it's stated that T: !Trait. So only prove that the negated obligation holds.
227+
if tcx.has_attr(a_def_id, sym::rustc_strict_coherence)
228+
&& tcx.has_attr(b_def_id, sym::rustc_strict_coherence)
229+
{
230+
o.flip_polarity(tcx)
227231
.as_ref()
228232
.map(|o| selcx.infcx().predicate_must_hold_modulo_regions(o))
229233
.unwrap_or(false)
234+
} else {
235+
!selcx.predicate_may_hold_fatal(o)
236+
|| o.flip_polarity(tcx)
237+
.as_ref()
238+
.map(|o| selcx.infcx().predicate_must_hold_modulo_regions(o))
239+
.unwrap_or(false)
240+
}
230241
});
231242
// FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported
232243
// to the canonical trait query form, `infcx.predicate_may_hold`, once
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![feature(negative_impls)]
2+
#![feature(rustc_attrs)]
3+
#![feature(trait_alias)]
4+
5+
trait A {}
6+
trait B {}
7+
trait AB = A + B;
8+
9+
impl !A for u32 {}
10+
11+
trait C {}
12+
#[rustc_strict_coherence]
13+
impl<T: AB> C for T {}
14+
#[rustc_strict_coherence]
15+
impl C for u32 {}
16+
//~^ ERROR: conflicting implementations of trait `C` for type `u32` [E0119]
17+
// FIXME this should work, we should implement an `assemble_neg_candidates` fn
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0119]: conflicting implementations of trait `C` for type `u32`
2+
--> $DIR/coherence-overlap-negate-alias-strict.rs:15:1
3+
|
4+
LL | impl<T: AB> C for T {}
5+
| ------------------- first implementation here
6+
LL | #[rustc_strict_coherence]
7+
LL | impl C for u32 {}
8+
| ^^^^^^^^^^^^^^ conflicting implementation for `u32`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0119`.
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(trait_alias)]
6+
7+
trait A {}
8+
trait B {}
9+
10+
impl !A for u32 {}
11+
12+
trait C {}
13+
#[rustc_strict_coherence]
14+
impl<T: A + B> C for T {}
15+
#[rustc_strict_coherence]
16+
impl C for u32 {}
17+
18+
fn main() {}

0 commit comments

Comments
 (0)