Skip to content

Commit 2c4df77

Browse files
authored
Rollup merge of rust-lang#40097 - sgrif:sg-implement-rfc-1268, r=nikomatsakis
Implement RFC 1268 This patch allows overlap to occur between any two impls of a trait for traits which have no associated items. Several compile-fail tests around coherence had to be changed to add at least one item to the trait they test against. Ref rust-lang#29864
2 parents 2564711 + 665f852 commit 2c4df77

26 files changed

+195
-22
lines changed

src/librustc/traits/select.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1724,7 +1724,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17241724
if other.evaluation == EvaluatedToOk {
17251725
if let ImplCandidate(victim_def) = victim.candidate {
17261726
let tcx = self.tcx().global_tcx();
1727-
return traits::specializes(tcx, other_def, victim_def);
1727+
return traits::specializes(tcx, other_def, victim_def) ||
1728+
tcx.impls_are_allowed_to_overlap(other_def, victim_def);
17281729
}
17291730
}
17301731

src/librustc/traits/specialize/specialization_graph.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ impl<'a, 'gcx, 'tcx> Children {
113113
possible_sibling,
114114
impl_def_id);
115115
if let Some(impl_header) = overlap {
116+
if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
117+
return Ok((false, false));
118+
}
119+
116120
let le = specializes(tcx, impl_def_id, possible_sibling);
117121
let ge = specializes(tcx, possible_sibling, impl_def_id);
118122

src/librustc/ty/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,6 +2158,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
21582158
queries::impl_trait_ref::get(self, DUMMY_SP, id)
21592159
}
21602160

2161+
/// Returns true if the impls are the same polarity and are implementing
2162+
/// a trait which contains no items
2163+
pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
2164+
if !self.sess.features.borrow().overlapping_marker_traits {
2165+
return false;
2166+
}
2167+
let trait1_is_empty = self.impl_trait_ref(def_id1)
2168+
.map_or(false, |trait_ref| {
2169+
self.associated_item_def_ids(trait_ref.def_id).is_empty()
2170+
});
2171+
let trait2_is_empty = self.impl_trait_ref(def_id2)
2172+
.map_or(false, |trait_ref| {
2173+
self.associated_item_def_ids(trait_ref.def_id).is_empty()
2174+
});
2175+
self.trait_impl_polarity(def_id1) == self.trait_impl_polarity(def_id2)
2176+
&& trait1_is_empty
2177+
&& trait2_is_empty
2178+
}
2179+
21612180
// Returns `ty::VariantDef` if `def` refers to a struct,
21622181
// or variant or their constructors, panics otherwise.
21632182
pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {

src/libsyntax/feature_gate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ declare_features! (
342342

343343
// See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
344344
(active, rvalue_static_promotion, "1.15.1", Some(38865)),
345+
346+
// Allows overlapping impls of marker traits
347+
(active, overlapping_marker_traits, "1.18.0", Some(29864)),
345348
);
346349

347350
declare_features! (

src/test/compile-fail/E0120.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
trait MyTrait {}
11+
trait MyTrait { fn foo() {} }
1212

1313
impl Drop for MyTrait {
1414
//~^ ERROR E0120

src/test/compile-fail/auxiliary/trait_impl_conflict.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
pub trait Foo {
12+
fn foo() {}
1213
}
1314

1415
impl Foo for isize {

src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![feature(optin_builtin_traits)]
12+
#![feature(overlapping_marker_traits)]
1213

1314
trait MyTrait {}
1415

@@ -20,8 +21,8 @@ impl<T: MyTrait> !Send for TestType<T> {}
2021
//~^ ERROR conflicting implementations of trait `std::marker::Send`
2122

2223
unsafe impl<T:'static> Send for TestType<T> {}
23-
//~^ ERROR conflicting implementations of trait `std::marker::Send`
2424

2525
impl !Send for TestType<i32> {}
26+
//~^ ERROR conflicting implementations of trait `std::marker::Send`
2627

2728
fn main() {}

src/test/compile-fail/coherence-default-trait-impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
#![feature(optin_builtin_traits)]
1212

13-
trait MyTrait {}
13+
trait MyTrait { fn foo() {} }
1414

1515
impl MyTrait for .. {}
1616
//~^ ERROR redundant default implementations of trait `MyTrait`

src/test/compile-fail/coherence-impls-send.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![feature(optin_builtin_traits)]
12+
#![feature(overlapping_marker_traits)]
1213

1314
use std::marker::Copy;
1415

@@ -34,7 +35,6 @@ unsafe impl Send for [MyType] {}
3435

3536
unsafe impl Send for &'static [NotSync] {}
3637
//~^ ERROR E0117
37-
//~| ERROR E0119
3838

3939
fn main() {
4040
}

src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// Test that you cannot *directly* dispatch on lifetime requirements
1212

13-
trait MyTrait {}
13+
trait MyTrait { fn foo() {} }
1414

1515
impl<T> MyTrait for T {}
1616
impl<T: 'static> MyTrait for T {} //~ ERROR E0119

0 commit comments

Comments
 (0)