Skip to content

Commit 8978bf6

Browse files
sgrifnikomatsakis
authored andcommitted
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
1 parent 5309a3e commit 8978bf6

20 files changed

+64
-21
lines changed

src/librustc/traits/specialize/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
155155
return r;
156156
}
157157

158+
if tcx.impl_always_allowed_to_overlap(impl1_def_id)
159+
&& tcx.impl_always_allowed_to_overlap(impl2_def_id) {
160+
return true;
161+
}
162+
158163
// The feature gate should prevent introducing new specializations, but not
159164
// taking advantage of upstream ones.
160165
if !tcx.sess.features.borrow().specialization &&

src/librustc/traits/specialize/specialization_graph.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ impl<'a, 'gcx, 'tcx> Children {
113113
possible_sibling,
114114
impl_def_id);
115115
if let Some(impl_header) = overlap {
116+
if tcx.impl_always_allowed_to_overlap(impl_def_id)
117+
&& tcx.impl_always_allowed_to_overlap(possible_sibling) {
118+
return Ok((true, true));
119+
}
120+
116121
let le = specializes(tcx, impl_def_id, possible_sibling);
117122
let ge = specializes(tcx, possible_sibling, impl_def_id);
118123

src/librustc/ty/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,6 +2158,16 @@ 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 impl is positive and is for a triat which contains
2162+
/// no items
2163+
pub fn impl_always_allowed_to_overlap(self, def_id: DefId) -> bool {
2164+
self.trait_impl_polarity(def_id) == hir::ImplPolarity::Positive
2165+
&& self.impl_trait_ref(def_id)
2166+
.map_or(false, |trait_ref| {
2167+
self.associated_item_def_ids(trait_ref.def_id).is_empty()
2168+
})
2169+
}
2170+
21612171
// Returns `ty::VariantDef` if `def` refers to a struct,
21622172
// or variant or their constructors, panics otherwise.
21632173
pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {

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/coherence-conflicting-negative-trait-impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ impl<T: MyTrait> !Send for TestType<T> {}
2020
//~^ ERROR conflicting implementations of trait `std::marker::Send`
2121

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

2524
impl !Send for TestType<i32> {}
25+
//~^ ERROR conflicting implementations of trait `std::marker::Send`
2626

2727
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: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ unsafe impl Send for [MyType] {}
3434

3535
unsafe impl Send for &'static [NotSync] {}
3636
//~^ ERROR E0117
37-
//~| ERROR E0119
3837

3938
fn main() {
4039
}

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

src/test/compile-fail/coherence-overlap-all-t-and-tuple.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// Seems pretty basic, but then there was issue #24241. :)
1818

1919
trait From<U> {
20+
fn foo() {}
2021
}
2122

2223
impl <T> From<T> for T {

src/test/compile-fail/coherence-overlap-messages.rs

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

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

1313
impl<T> Foo for T {}
1414
impl<U> Foo for U {} //~ ERROR conflicting implementations of trait `Foo`:
1515

16-
trait Bar {}
16+
trait Bar { fn bar() {} }
1717

1818
impl<T> Bar for (T, u8) {}
1919
impl<T> Bar for (u8, T) {} //~ ERROR conflicting implementations of trait `Bar` for type `(u8, u8)`:
2020

21-
trait Baz<T> {}
21+
trait Baz<T> { fn baz() {} }
2222

2323
impl<T> Baz<u8> for T {}
2424
impl<T> Baz<T> for u8 {} //~ ERROR conflicting implementations of trait `Baz<u8>` for type `u8`:
2525

26-
trait Quux<U, V> {}
26+
trait Quux<U, V> { fn quux() {} }
2727

2828
impl<T, U, V> Quux<U, V> for T {}
2929
impl<T, U> Quux<U, U> for T {} //~ ERROR conflicting implementations of trait `Quux<_, _>`:

0 commit comments

Comments
 (0)