]> git.lizzy.rs Git - rust.git/commitdiff
Implement RFC 1268
authorSean Griffin <sean@seantheprogrammer.com>
Sat, 25 Feb 2017 21:16:27 +0000 (16:16 -0500)
committerCorey Farwell <coreyf@rwell.org>
Sat, 15 Apr 2017 02:04:53 +0000 (22:04 -0400)
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 #29864

20 files changed:
src/librustc/traits/specialize/mod.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/ty/mod.rs
src/test/compile-fail/E0120.rs
src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs
src/test/compile-fail/coherence-default-trait-impl.rs
src/test/compile-fail/coherence-impls-send.rs
src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs
src/test/compile-fail/coherence-overlap-all-t-and-tuple.rs
src/test/compile-fail/coherence-overlap-messages.rs
src/test/compile-fail/coherence-projection-conflict-orphan.rs
src/test/compile-fail/coherence-projection-conflict-ty-param.rs
src/test/compile-fail/coherence-projection-conflict.rs
src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs
src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs
src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs
src/test/compile-fail/coherence_copy_like_err_struct.rs
src/test/compile-fail/coherence_copy_like_err_tuple.rs
src/test/compile-fail/specialization/specialization-overlap.rs
src/test/run-pass/overlap-permitted-for-marker-traits.rs [new file with mode: 0644]

index 50a4d982832ace739c8c78b7afac69938d07f6c7..6455de48a299dfe54568d554d48110e4274d2aa0 100644 (file)
@@ -155,6 +155,11 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return r;
     }
 
+    if tcx.impl_always_allowed_to_overlap(impl1_def_id)
+        && tcx.impl_always_allowed_to_overlap(impl2_def_id) {
+        return true;
+    }
+
     // The feature gate should prevent introducing new specializations, but not
     // taking advantage of upstream ones.
     if !tcx.sess.features.borrow().specialization &&
index 40eb69395678f2bd63d39a03d35b980e9d0524e9..87abe681d39380491bc761cd3c78aefb96e3fd9a 100644 (file)
@@ -113,6 +113,11 @@ fn insert(&mut self,
                                                         possible_sibling,
                                                         impl_def_id);
                 if let Some(impl_header) = overlap {
+                    if tcx.impl_always_allowed_to_overlap(impl_def_id)
+                        && tcx.impl_always_allowed_to_overlap(possible_sibling) {
+                        return Ok((true, true));
+                    }
+
                     let le = specializes(tcx, impl_def_id, possible_sibling);
                     let ge = specializes(tcx, possible_sibling, impl_def_id);
 
index 8ff91583d0822f7ba57365e9d62b0023e1fe0b64..9fdabd38d4ab448cf5569ac5fcebb909e0b6262c 100644 (file)
@@ -2227,6 +2227,16 @@ pub fn impl_trait_ref(self, id: DefId) -> Option<TraitRef<'gcx>> {
         queries::impl_trait_ref::get(self, DUMMY_SP, id)
     }
 
+    /// Returns true if the impl is positive and is for a triat which contains
+    /// no items
+    pub fn impl_always_allowed_to_overlap(self, def_id: DefId) -> bool {
+        self.trait_impl_polarity(def_id) == hir::ImplPolarity::Positive
+            && self.impl_trait_ref(def_id)
+                .map_or(false, |trait_ref| {
+                    self.associated_item_def_ids(trait_ref.def_id).is_empty()
+                })
+    }
+
     // Returns `ty::VariantDef` if `def` refers to a struct,
     // or variant or their constructors, panics otherwise.
     pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {
index 3fdeb7531754021d2f7ae780f039fb672df6265d..80cc0d2680f7c5a7456d22ade460122aaf963eeb 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-trait MyTrait {}
+trait MyTrait { fn foo() {} }
 
 impl Drop for MyTrait {
               //~^ ERROR E0120
index 7fd1b17f2966c9c1baae5155e76c9426f1aa0845..d841e8c41d984e0b40fd2347d6a185621c4123ad 100644 (file)
@@ -20,8 +20,8 @@ impl<T: MyTrait> !Send for TestType<T> {}
 //~^ ERROR conflicting implementations of trait `std::marker::Send`
 
 unsafe impl<T:'static> Send for TestType<T> {}
-//~^ ERROR conflicting implementations of trait `std::marker::Send`
 
 impl !Send for TestType<i32> {}
+//~^ ERROR conflicting implementations of trait `std::marker::Send`
 
 fn main() {}
index 15a80c64f8b0621fcd07d054ba4580a01e914377..e6bf068156c2b037fcf4d99a987cfc8a2e6c9c74 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(optin_builtin_traits)]
 
-trait MyTrait {}
+trait MyTrait { fn foo() {} }
 
 impl MyTrait for .. {}
 //~^ ERROR redundant default implementations of trait `MyTrait`
index f130a9353516f527462a79183cb49b4436ad7257..d0e6bc6a1c699264b016d9acb994098f494f3cd8 100644 (file)
@@ -34,7 +34,6 @@ unsafe impl Send for [MyType] {}
 
 unsafe impl Send for &'static [NotSync] {}
 //~^ ERROR E0117
-//~| ERROR E0119
 
 fn main() {
 }
index 6de338f1db0fae9b781d5ed1e412899dd08d75cc..47026cd32d411a6f51033000677c775d1e657c7f 100644 (file)
@@ -10,7 +10,7 @@
 
 // Test that you cannot *directly* dispatch on lifetime requirements
 
-trait MyTrait {}
+trait MyTrait { fn foo() {} }
 
 impl<T> MyTrait for T {}
 impl<T: 'static> MyTrait for T {} //~ ERROR E0119
index 928ba7a36db266ddb3534eba302fbff8125d4013..1fad608db6c3b1a3e52c5c1e62d0f7746a22ad0d 100644 (file)
@@ -17,6 +17,7 @@
 // Seems pretty basic, but then there was issue #24241. :)
 
 trait From<U> {
+    fn foo() {}
 }
 
 impl <T> From<T> for T {
index 0ae8135221c21fc9a54f3094a711234c17ce9bff..a10deeafbe67e267f3b7100f3584436696b61cb9 100644 (file)
@@ -8,22 +8,22 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-trait Foo {}
+trait Foo { fn foo() {} }
 
 impl<T> Foo for T {}
 impl<U> Foo for U {} //~ ERROR conflicting implementations of trait `Foo`:
 
-trait Bar {}
+trait Bar { fn bar() {} }
 
 impl<T> Bar for (T, u8) {}
 impl<T> Bar for (u8, T) {} //~ ERROR conflicting implementations of trait `Bar` for type `(u8, u8)`:
 
-trait Baz<T> {}
+trait Baz<T> { fn baz() {} }
 
 impl<T> Baz<u8> for T {}
 impl<T> Baz<T> for u8 {} //~ ERROR conflicting implementations of trait `Baz<u8>` for type `u8`:
 
-trait Quux<U, V> {}
+trait Quux<U, V> { fn quux() {} }
 
 impl<T, U, V> Quux<U, V> for T {}
 impl<T, U> Quux<U, U> for T {} //~ ERROR conflicting implementations of trait `Quux<_, _>`:
index 3ed3549de89aaa214b9191d281a47429c741af58..784ff0cd5e0aa72982f288efcfbaf92cd34d88bc 100644 (file)
@@ -15,7 +15,7 @@
 // due to the orphan rules. Therefore, `A::Item` may yet turn out to
 // be `i32`.
 
-pub trait Foo<P> {}
+pub trait Foo<P> { fn foo() {} }
 
 pub trait Bar {
     type Output: 'static;
index f04902a70f68c20e490b1719efaefe4b58d38096..120d9046389a18fb3a5d834c39b132049b3cb401 100644 (file)
@@ -13,7 +13,7 @@
 
 use std::marker::PhantomData;
 
-pub trait Foo<P> {}
+pub trait Foo<P> { fn foo() {} }
 
 impl <P, T: Foo<P>> Foo<P> for Option<T> {}
 
index 6d3ab32f06f43d08327af11f3d2088ae8c643935..3c32ab38b93dc15da014d66ad612824a6a4c012f 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::marker::PhantomData;
 
-pub trait Foo<P> {}
+pub trait Foo<P> { fn foo() {} }
 
 pub trait Bar {
     type Output: 'static;
index fcd6e5c4952074807d0ed8abe876b71956282b0a..9fbb7aa4cb1a7f70a180821a46bd137fdda6503a 100644 (file)
@@ -20,7 +20,7 @@
 
 struct MyType { x: i32 }
 
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
 impl<T: lib::MyCopy> MyTrait for T { }
 
 // `MyFundamentalStruct` is declared fundamental, so we can test that
index b5c0a7fb5f564829fda4f13331cb4089ec3ed696..2f6dca4f3c2715ae4915cab7ea847f7dc1f401a6 100644 (file)
@@ -20,7 +20,7 @@
 
 struct MyType { x: i32 }
 
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
 impl<T: lib::MyCopy> MyTrait for T { }
 
 // `MyFundamentalStruct` is declared fundamental, so we can test that
index 8e3e3f31cb5f1434356b5b9aa5bfd199a475cf8f..f424e8872010f25d5d4414a5ff07d1e3d636f48f 100644 (file)
@@ -19,7 +19,7 @@
 
 struct MyType { x: i32 }
 
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
 
 impl<T: lib::MyCopy> MyTrait for T { }
 
index 35bc17b8e887036a93bb4e1675aca4786795e1d8..04262e65c5a2afe8d2ff72e4113ce08165ef35ae 100644 (file)
@@ -17,7 +17,7 @@
 
 struct MyType { x: i32 }
 
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
 impl<T: lib::MyCopy> MyTrait for T { }
 
 // `MyStruct` is not declared fundamental, therefore this would
index a70cc92955fb0d6a76e0a5672e0d4764a976d470..378a70864f0eedb93cf06ff9988b8ff55eabccc8 100644 (file)
@@ -17,7 +17,7 @@
 
 struct MyType { x: i32 }
 
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
 impl<T: lib::MyCopy> MyTrait for T { }
 
 // Tuples are not fundamental, therefore this would require that
index f579817100107c88452fd1b64800b50b8ca8efd6..ff12a82db5b7dff2ded854e7a4de119bd7800cd4 100644 (file)
 
 #![feature(specialization)]
 
-trait Foo {}
+trait Foo { fn foo() {} }
 impl<T: Clone> Foo for T {}
 impl<T> Foo for Vec<T> {} //~ ERROR E0119
 
-trait Bar {}
+trait Bar { fn bar() {} }
 impl<T> Bar for (T, u8) {}
 impl<T> Bar for (u8, T) {} //~ ERROR E0119
 
-trait Baz<U> {}
+trait Baz<U> { fn baz() {} }
 impl<T> Baz<T> for u8 {}
 impl<T> Baz<u8> for T {} //~ ERROR E0119
 
-trait Qux {}
+trait Qux { fn qux() {} }
 impl<T: Clone> Qux for T {}
 impl<T: Eq> Qux for T {} //~ ERROR E0119
 
diff --git a/src/test/run-pass/overlap-permitted-for-marker-traits.rs b/src/test/run-pass/overlap-permitted-for-marker-traits.rs
new file mode 100644 (file)
index 0000000..66c45e6
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait MyMarker {}
+
+impl<T: Copy> MyMarker for T {}
+impl<T: Eq> MyMarker for T {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+    t
+}
+
+fn main() {
+    assert_eq!(1, foo(1));
+    assert_eq!(vec![1], foo(vec![1]));
+}