about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-04-15 02:06:20 +0000
committerbors <bors@rust-lang.org>2017-04-15 02:06:20 +0000
commitbe1a74e4d3e629a350928e850514541782b46fdd (patch)
treeadd43bd1e97808670711899ce2e6a222ccdd51ff
parentf0ca5d4bad07a4fc8497bd9766cdadaee1bd0ac6 (diff)
parent3adcd1c37e38c57066837152dff02cf0c9ba6e23 (diff)
downloadrust-be1a74e4d3e629a350928e850514541782b46fdd.tar.gz
rust-be1a74e4d3e629a350928e850514541782b46fdd.zip
Auto merge of #41312 - frewsxcv:rollup, r=frewsxcv
Rollup of 2 pull requests

- Successful merges: #41125, #41309
- Failed merges:
-rw-r--r--src/doc/unstable-book/src/SUMMARY.md1
-rw-r--r--src/doc/unstable-book/src/overlapping-marker-traits.md7
-rw-r--r--src/libcore/hash/mod.rs197
-rw-r--r--src/librustc/traits/select.rs3
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs4
-rw-r--r--src/librustc/ty/mod.rs19
-rw-r--r--src/libsyntax/feature_gate.rs3
-rw-r--r--src/test/compile-fail/E0120.rs2
-rw-r--r--src/test/compile-fail/auxiliary/trait_impl_conflict.rs1
-rw-r--r--src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs3
-rw-r--r--src/test/compile-fail/coherence-default-trait-impl.rs2
-rw-r--r--src/test/compile-fail/coherence-impls-send.rs2
-rw-r--r--src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs2
-rw-r--r--src/test/compile-fail/coherence-overlap-all-t-and-tuple.rs1
-rw-r--r--src/test/compile-fail/coherence-overlap-messages.rs8
-rw-r--r--src/test/compile-fail/coherence-projection-conflict-orphan.rs2
-rw-r--r--src/test/compile-fail/coherence-projection-conflict-ty-param.rs2
-rw-r--r--src/test/compile-fail/coherence-projection-conflict.rs2
-rw-r--r--src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs2
-rw-r--r--src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs2
-rw-r--r--src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs2
-rw-r--r--src/test/compile-fail/coherence_copy_like_err_struct.rs2
-rw-r--r--src/test/compile-fail/coherence_copy_like_err_tuple.rs2
-rw-r--r--src/test/compile-fail/feature-gate-overlapping_marker_traits.rs19
-rw-r--r--src/test/compile-fail/overlap-marker-trait.rs41
-rw-r--r--src/test/compile-fail/specialization/specialization-overlap.rs8
-rw-r--r--src/test/run-pass/overlap-doesnt-conflict-with-specialization.rs27
-rw-r--r--src/test/run-pass/overlap-permitted-for-marker-traits-neg.rs20
-rw-r--r--src/test/run-pass/overlap-permitted-for-marker-traits.rs36
29 files changed, 367 insertions, 55 deletions
diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md
index a5599395f79..a9796fdf01e 100644
--- a/src/doc/unstable-book/src/SUMMARY.md
+++ b/src/doc/unstable-book/src/SUMMARY.md
@@ -136,6 +136,7 @@
 - [optin_builtin_traits](optin-builtin-traits.md)
 - [option_entry](option-entry.md)
 - [osstring_shrink_to_fit](osstring-shrink-to-fit.md)
+- [overlapping_marker_traits](overlapping-marker-traits.md)
 - [panic_abort](panic-abort.md)
 - [panic_runtime](panic-runtime.md)
 - [panic_unwind](panic-unwind.md)
diff --git a/src/doc/unstable-book/src/overlapping-marker-traits.md b/src/doc/unstable-book/src/overlapping-marker-traits.md
new file mode 100644
index 00000000000..a4920839c6c
--- /dev/null
+++ b/src/doc/unstable-book/src/overlapping-marker-traits.md
@@ -0,0 +1,7 @@
+# `overlapping_marker_traits`
+
+The tracking issue for this feature is: [#29864]
+
+[#29864]: https://github.com/rust-lang/rust/issues/29864
+
+------------------------
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 756d472eca8..f68361e8522 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -107,29 +107,25 @@ mod sip;
 
 /// A hashable type.
 ///
-/// The `H` type parameter is an abstract hash state that is used by the `Hash`
-/// to compute the hash.
+/// Types implementing `Hash` are able to be [`hash`]ed with an instance of
+/// [`Hasher`].
 ///
-/// If you are also implementing [`Eq`], there is an additional property that
-/// is important:
+/// ## Implementing `Hash`
 ///
-/// ```text
-/// k1 == k2 -> hash(k1) == hash(k2)
-/// ```
-///
-/// In other words, if two keys are equal, their hashes should also be equal.
-/// [`HashMap`] and [`HashSet`] both rely on this behavior.
+/// You can derive `Hash` with `#[derive(Hash)]` if all fields implement `Hash`.
+/// The resulting hash will be the combination of the values from calling
+/// [`hash`] on each field.
 ///
-/// ## Derivable
-///
-/// This trait can be used with `#[derive]` if all fields implement `Hash`.
-/// When `derive`d, the resulting hash will be the combination of the values
-/// from calling [`.hash`] on each field.
-///
-/// ## How can I implement `Hash`?
+/// ```
+/// #[derive(Hash)]
+/// struct Rustacean {
+///     name: String,
+///     country: String,
+/// }
+/// ```
 ///
-/// If you need more control over how a value is hashed, you need to implement
-/// the `Hash` trait:
+/// If you need more control over how a value is hashed, you can of course
+/// implement the `Hash` trait yourself:
 ///
 /// ```
 /// use std::hash::{Hash, Hasher};
@@ -148,17 +144,60 @@ mod sip;
 /// }
 /// ```
 ///
+/// ## `Hash` and `Eq`
+///
+/// When implementing both `Hash` and [`Eq`], it is important that the following
+/// property holds:
+///
+/// ```text
+/// k1 == k2 -> hash(k1) == hash(k2)
+/// ```
+///
+/// In other words, if two keys are equal, their hashes must also be equal.
+/// [`HashMap`] and [`HashSet`] both rely on this behavior.
+///
+/// Thankfully, you won't need to worry about upholding this property when
+/// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`.
+///
 /// [`Eq`]: ../../std/cmp/trait.Eq.html
+/// [`Hasher`]: trait.Hasher.html
 /// [`HashMap`]: ../../std/collections/struct.HashMap.html
 /// [`HashSet`]: ../../std/collections/struct.HashSet.html
-/// [`.hash`]: #tymethod.hash
+/// [`hash`]: #tymethod.hash
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Hash {
-    /// Feeds this value into the state given, updating the hasher as necessary.
+    /// Feeds this value into the given [`Hasher`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::hash_map::DefaultHasher;
+    /// use std::hash::{Hash, Hasher};
+    ///
+    /// let mut hasher = DefaultHasher::new();
+    /// 7920.hash(&mut hasher);
+    /// println!("Hash is {:x}!", hasher.finish());
+    /// ```
+    ///
+    /// [`Hasher`]: trait.Hasher.html
     #[stable(feature = "rust1", since = "1.0.0")]
     fn hash<H: Hasher>(&self, state: &mut H);
 
-    /// Feeds a slice of this type into the state provided.
+    /// Feeds a slice of this type into the given [`Hasher`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::hash_map::DefaultHasher;
+    /// use std::hash::{Hash, Hasher};
+    ///
+    /// let mut hasher = DefaultHasher::new();
+    /// let numbers = [6, 28, 496, 8128];
+    /// Hash::hash_slice(&numbers, &mut hasher);
+    /// println!("Hash is {:x}!", hasher.finish());
+    /// ```
+    ///
+    /// [`Hasher`]: trait.Hasher.html
     #[stable(feature = "hash_slice", since = "1.3.0")]
     fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
         where Self: Sized
@@ -169,18 +208,73 @@ pub trait Hash {
     }
 }
 
-/// A trait which represents the ability to hash an arbitrary stream of bytes.
+/// A trait for hashing an arbitrary stream of bytes.
+///
+/// Instances of `Hasher` usually represent state that is changed while hashing
+/// data.
+///
+/// `Hasher` provides a fairly basic interface for retrieving the generated hash
+/// (with [`finish`]), and writing integers as well as slices of bytes into an
+/// instance (with [`write`] and [`write_u8`] etc.). Most of the time, `Hasher`
+/// instances are used in conjunction with the [`Hash`] trait.
+///
+/// # Examples
+///
+/// ```
+/// use std::collections::hash_map::DefaultHasher;
+/// use std::hash::Hasher;
+///
+/// let mut hasher = DefaultHasher::new();
+///
+/// hasher.write_u32(1989);
+/// hasher.write_u8(11);
+/// hasher.write_u8(9);
+/// hasher.write(b"Huh?");
+///
+/// println!("Hash is {:x}!", hasher.finish());
+/// ```
+///
+/// [`Hash`]: trait.Hash.html
+/// [`finish`]: #tymethod.finish
+/// [`write`]: #tymethod.write
+/// [`write_u8`]: #method.write_u8
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Hasher {
     /// Completes a round of hashing, producing the output hash generated.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::hash_map::DefaultHasher;
+    /// use std::hash::Hasher;
+    ///
+    /// let mut hasher = DefaultHasher::new();
+    /// hasher.write(b"Cool!");
+    ///
+    /// println!("Hash is {:x}!", hasher.finish());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn finish(&self) -> u64;
 
     /// Writes some data into this `Hasher`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::hash_map::DefaultHasher;
+    /// use std::hash::Hasher;
+    ///
+    /// let mut hasher = DefaultHasher::new();
+    /// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
+    ///
+    /// hasher.write(&data);
+    ///
+    /// println!("Hash is {:x}!", hasher.finish());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn write(&mut self, bytes: &[u8]);
 
-    /// Write a single `u8` into this hasher.
+    /// Writes a single `u8` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_u8(&mut self, i: u8) {
@@ -258,12 +352,35 @@ pub trait Hasher {
     }
 }
 
-/// A `BuildHasher` is typically used as a factory for instances of `Hasher`
-/// which a `HashMap` can then use to hash keys independently.
+/// A trait for creating instances of [`Hasher`].
+///
+/// A `BuildHasher` is typically used (e.g. by [`HashMap`]) to create
+/// [`Hasher`]s for each key such that they are hashed independently of one
+/// another, since [`Hasher`]s contain state.
+///
+/// For each instance of `BuildHasher`, the [`Hasher`]s created by
+/// [`build_hasher`] should be identical. That is, if the same stream of bytes
+/// is fed into each hasher, the same output will also be generated.
+///
+/// # Examples
+///
+/// ```
+/// use std::collections::hash_map::RandomState;
+/// use std::hash::{BuildHasher, Hasher};
+///
+/// let s = RandomState::new();
+/// let mut hasher_1 = s.build_hasher();
+/// let mut hasher_2 = s.build_hasher();
 ///
-/// Note that for each instance of `BuildHasher`, the created hashers should be
-/// identical. That is, if the same stream of bytes is fed into each hasher, the
-/// same output will also be generated.
+/// hasher_1.write_u32(8128);
+/// hasher_2.write_u32(8128);
+///
+/// assert_eq!(hasher_1.finish(), hasher_2.finish());
+/// ```
+///
+/// [`build_hasher`]: #tymethod.build_hasher
+/// [`Hasher`]: trait.Hasher.html
+/// [`HashMap`]: ../../std/collections/struct.HashMap.html
 #[stable(since = "1.7.0", feature = "build_hasher")]
 pub trait BuildHasher {
     /// Type of the hasher that will be created.
@@ -272,6 +389,9 @@ pub trait BuildHasher {
 
     /// Creates a new hasher.
     ///
+    /// Each call to `build_hasher` on the same instance should produce identical
+    /// [`Hasher`]s.
+    ///
     /// # Examples
     ///
     /// ```
@@ -281,15 +401,23 @@ pub trait BuildHasher {
     /// let s = RandomState::new();
     /// let new_s = s.build_hasher();
     /// ```
+    ///
+    /// [`Hasher`]: trait.Hasher.html
     #[stable(since = "1.7.0", feature = "build_hasher")]
     fn build_hasher(&self) -> Self::Hasher;
 }
 
-/// The `BuildHasherDefault` structure is used in scenarios where one has a
-/// type that implements [`Hasher`] and [`Default`], but needs that type to
-/// implement [`BuildHasher`].
+/// Used to create a default [`BuildHasher`] instance for types that implement
+/// [`Hasher`] and [`Default`].
 ///
-/// This structure is zero-sized and does not need construction.
+/// `BuildHasherDefault<H>` can be used when a type `H` implements [`Hasher`] and
+/// [`Default`], and you need a corresponding [`BuildHasher`] instance, but none is
+/// defined.
+///
+/// Any `BuildHasherDefault` is [zero-sized]. It can be created with
+/// [`default`][method.Default]. When using `BuildHasherDefault` with [`HashMap`] or
+/// [`HashSet`], this doesn't need to be done, since they implement appropriate
+/// [`Default`] instances themselves.
 ///
 /// # Examples
 ///
@@ -322,8 +450,11 @@ pub trait BuildHasher {
 ///
 /// [`BuildHasher`]: trait.BuildHasher.html
 /// [`Default`]: ../default/trait.Default.html
+/// [method.default]: #method.default
 /// [`Hasher`]: trait.Hasher.html
 /// [`HashMap`]: ../../std/collections/struct.HashMap.html
+/// [`HashSet`]: ../../std/collections/struct.HashSet.html
+/// [zero-sized]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts
 #[stable(since = "1.7.0", feature = "build_hasher")]
 pub struct BuildHasherDefault<H>(marker::PhantomData<H>);
 
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 67d50210ba3..410eb2b8484 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1736,7 +1736,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 if other.evaluation == EvaluatedToOk {
                     if let ImplCandidate(victim_def) = victim.candidate {
                         let tcx = self.tcx().global_tcx();
-                        return traits::specializes(tcx, other_def, victim_def);
+                        return traits::specializes(tcx, other_def, victim_def) ||
+                            tcx.impls_are_allowed_to_overlap(other_def, victim_def);
                     }
                 }
 
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index 40eb6939567..6e2c16c82ae 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -113,6 +113,10 @@ impl<'a, 'gcx, 'tcx> Children {
                                                         possible_sibling,
                                                         impl_def_id);
                 if let Some(impl_header) = overlap {
+                    if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
+                        return Ok((false, false));
+                    }
+
                     let le = specializes(tcx, impl_def_id, possible_sibling);
                     let ge = specializes(tcx, possible_sibling, impl_def_id);
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 8ff91583d08..3da9383762b 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2227,6 +2227,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         queries::impl_trait_ref::get(self, DUMMY_SP, id)
     }
 
+    /// Returns true if the impls are the same polarity and are implementing
+    /// a trait which contains no items
+    pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
+        if !self.sess.features.borrow().overlapping_marker_traits {
+            return false;
+        }
+        let trait1_is_empty = self.impl_trait_ref(def_id1)
+            .map_or(false, |trait_ref| {
+                self.associated_item_def_ids(trait_ref.def_id).is_empty()
+            });
+        let trait2_is_empty = self.impl_trait_ref(def_id2)
+            .map_or(false, |trait_ref| {
+                self.associated_item_def_ids(trait_ref.def_id).is_empty()
+            });
+        self.trait_impl_polarity(def_id1) == self.trait_impl_polarity(def_id2)
+            && trait1_is_empty
+            && trait2_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 {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 8b62416dcbd..6e455234196 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -349,6 +349,9 @@ declare_features! (
 
     // Allows module-level inline assembly by way of global_asm!()
     (active, global_asm, "1.18.0", Some(35119)),
+
+    // Allows overlapping impls of marker traits
+    (active, overlapping_marker_traits, "1.18.0", Some(29864)),
 );
 
 declare_features! (
diff --git a/src/test/compile-fail/E0120.rs b/src/test/compile-fail/E0120.rs
index 3fdeb753175..80cc0d2680f 100644
--- a/src/test/compile-fail/E0120.rs
+++ b/src/test/compile-fail/E0120.rs
@@ -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
diff --git a/src/test/compile-fail/auxiliary/trait_impl_conflict.rs b/src/test/compile-fail/auxiliary/trait_impl_conflict.rs
index c3ecbb014dc..3190ce430ad 100644
--- a/src/test/compile-fail/auxiliary/trait_impl_conflict.rs
+++ b/src/test/compile-fail/auxiliary/trait_impl_conflict.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 pub trait Foo {
+    fn foo() {}
 }
 
 impl Foo for isize {
diff --git a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs
index 7fd1b17f296..8e9d1eff345 100644
--- a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs
+++ b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(optin_builtin_traits)]
+#![feature(overlapping_marker_traits)]
 
 trait MyTrait {}
 
@@ -20,8 +21,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() {}
diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs
index 15a80c64f8b..e6bf068156c 100644
--- a/src/test/compile-fail/coherence-default-trait-impl.rs
+++ b/src/test/compile-fail/coherence-default-trait-impl.rs
@@ -10,7 +10,7 @@
 
 #![feature(optin_builtin_traits)]
 
-trait MyTrait {}
+trait MyTrait { fn foo() {} }
 
 impl MyTrait for .. {}
 //~^ ERROR redundant default implementations of trait `MyTrait`
diff --git a/src/test/compile-fail/coherence-impls-send.rs b/src/test/compile-fail/coherence-impls-send.rs
index f130a935351..9caaee41aeb 100644
--- a/src/test/compile-fail/coherence-impls-send.rs
+++ b/src/test/compile-fail/coherence-impls-send.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(optin_builtin_traits)]
+#![feature(overlapping_marker_traits)]
 
 use std::marker::Copy;
 
@@ -34,7 +35,6 @@ unsafe impl Send for [MyType] {}
 
 unsafe impl Send for &'static [NotSync] {}
 //~^ ERROR E0117
-//~| ERROR E0119
 
 fn main() {
 }
diff --git a/src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs b/src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs
index 6de338f1db0..47026cd32d4 100644
--- a/src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs
+++ b/src/test/compile-fail/coherence-no-direct-lifetime-dispatch.rs
@@ -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
diff --git a/src/test/compile-fail/coherence-overlap-all-t-and-tuple.rs b/src/test/compile-fail/coherence-overlap-all-t-and-tuple.rs
index 928ba7a36db..1fad608db6c 100644
--- a/src/test/compile-fail/coherence-overlap-all-t-and-tuple.rs
+++ b/src/test/compile-fail/coherence-overlap-all-t-and-tuple.rs
@@ -17,6 +17,7 @@
 // Seems pretty basic, but then there was issue #24241. :)
 
 trait From<U> {
+    fn foo() {}
 }
 
 impl <T> From<T> for T {
diff --git a/src/test/compile-fail/coherence-overlap-messages.rs b/src/test/compile-fail/coherence-overlap-messages.rs
index 0ae8135221c..a10deeafbe6 100644
--- a/src/test/compile-fail/coherence-overlap-messages.rs
+++ b/src/test/compile-fail/coherence-overlap-messages.rs
@@ -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<_, _>`:
diff --git a/src/test/compile-fail/coherence-projection-conflict-orphan.rs b/src/test/compile-fail/coherence-projection-conflict-orphan.rs
index 3ed3549de89..784ff0cd5e0 100644
--- a/src/test/compile-fail/coherence-projection-conflict-orphan.rs
+++ b/src/test/compile-fail/coherence-projection-conflict-orphan.rs
@@ -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;
diff --git a/src/test/compile-fail/coherence-projection-conflict-ty-param.rs b/src/test/compile-fail/coherence-projection-conflict-ty-param.rs
index f04902a70f6..120d9046389 100644
--- a/src/test/compile-fail/coherence-projection-conflict-ty-param.rs
+++ b/src/test/compile-fail/coherence-projection-conflict-ty-param.rs
@@ -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> {}
 
diff --git a/src/test/compile-fail/coherence-projection-conflict.rs b/src/test/compile-fail/coherence-projection-conflict.rs
index 6d3ab32f06f..3c32ab38b93 100644
--- a/src/test/compile-fail/coherence-projection-conflict.rs
+++ b/src/test/compile-fail/coherence-projection-conflict.rs
@@ -10,7 +10,7 @@
 
 use std::marker::PhantomData;
 
-pub trait Foo<P> {}
+pub trait Foo<P> { fn foo() {} }
 
 pub trait Bar {
     type Output: 'static;
diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs
index fcd6e5c4952..9fbb7aa4cb1 100644
--- a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs
+++ b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs
@@ -20,7 +20,7 @@ extern crate coherence_copy_like_lib as lib;
 
 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
diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs
index b5c0a7fb5f5..2f6dca4f3c2 100644
--- a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs
+++ b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs
@@ -20,7 +20,7 @@ extern crate coherence_copy_like_lib as lib;
 
 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
diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs
index 8e3e3f31cb5..f424e887201 100644
--- a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs
+++ b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs
@@ -19,7 +19,7 @@ extern crate coherence_copy_like_lib as lib;
 
 struct MyType { x: i32 }
 
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
 
 impl<T: lib::MyCopy> MyTrait for T { }
 
diff --git a/src/test/compile-fail/coherence_copy_like_err_struct.rs b/src/test/compile-fail/coherence_copy_like_err_struct.rs
index 35bc17b8e88..04262e65c5a 100644
--- a/src/test/compile-fail/coherence_copy_like_err_struct.rs
+++ b/src/test/compile-fail/coherence_copy_like_err_struct.rs
@@ -17,7 +17,7 @@ extern crate coherence_copy_like_lib as lib;
 
 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
diff --git a/src/test/compile-fail/coherence_copy_like_err_tuple.rs b/src/test/compile-fail/coherence_copy_like_err_tuple.rs
index a70cc92955f..378a70864f0 100644
--- a/src/test/compile-fail/coherence_copy_like_err_tuple.rs
+++ b/src/test/compile-fail/coherence_copy_like_err_tuple.rs
@@ -17,7 +17,7 @@ extern crate coherence_copy_like_lib as lib;
 
 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
diff --git a/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs b/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs
new file mode 100644
index 00000000000..d2aa4e59b5b
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs
@@ -0,0 +1,19 @@
+// 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.
+
+use std::fmt::{Debug, Display};
+
+trait MyMarker {}
+
+impl<T: Display> MyMarker for T {}
+impl<T: Debug> MyMarker for T {}
+//~^ ERROR E0119
+
+fn main() {}
diff --git a/src/test/compile-fail/overlap-marker-trait.rs b/src/test/compile-fail/overlap-marker-trait.rs
new file mode 100644
index 00000000000..a649ae25f34
--- /dev/null
+++ b/src/test/compile-fail/overlap-marker-trait.rs
@@ -0,0 +1,41 @@
+// 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.
+
+// Test for RFC 1268: we allow overlapping impls of marker traits,
+// that is, traits without items. In this case, a type `T` is
+// `MyMarker` if it is either `Debug` or `Display`. This test just
+// checks that we don't consider **all** types to be `MyMarker`.  See
+// also the companion test in
+// `run-pass/overlap-permitted-for-marker-traits.rs`.
+
+#![feature(overlapping_marker_traits)]
+#![feature(optin_builtin_traits)]
+
+use std::fmt::{Debug, Display};
+
+trait Marker {}
+
+impl<T: Debug> Marker for T {}
+impl<T: Display> Marker for T {}
+
+fn is_marker<T: Marker>() { }
+
+struct NotDebugOrDisplay;
+
+fn main() {
+    // Debug && Display:
+    is_marker::<i32>();
+
+    // Debug && !Display:
+    is_marker::<Vec<i32>>();
+
+    // !Debug && !Display
+    is_marker::<NotDebugOrDisplay>(); //~ ERROR
+}
diff --git a/src/test/compile-fail/specialization/specialization-overlap.rs b/src/test/compile-fail/specialization/specialization-overlap.rs
index f5798171001..ff12a82db5b 100644
--- a/src/test/compile-fail/specialization/specialization-overlap.rs
+++ b/src/test/compile-fail/specialization/specialization-overlap.rs
@@ -10,19 +10,19 @@
 
 #![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-doesnt-conflict-with-specialization.rs b/src/test/run-pass/overlap-doesnt-conflict-with-specialization.rs
new file mode 100644
index 00000000000..ed45d81c0d6
--- /dev/null
+++ b/src/test/run-pass/overlap-doesnt-conflict-with-specialization.rs
@@ -0,0 +1,27 @@
+// 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.
+
+#![feature(overlapping_marker_traits)]
+#![feature(specialization)]
+
+trait MyMarker {}
+
+impl<T> MyMarker for T {}
+impl<T> MyMarker for Vec<T> {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+    t
+}
+
+fn main() {
+    assert_eq!(1, foo(1));
+    assert_eq!(2.0, foo(2.0));
+    assert_eq!(vec![1], foo(vec![1]));
+}
diff --git a/src/test/run-pass/overlap-permitted-for-marker-traits-neg.rs b/src/test/run-pass/overlap-permitted-for-marker-traits-neg.rs
new file mode 100644
index 00000000000..740d5d22ab5
--- /dev/null
+++ b/src/test/run-pass/overlap-permitted-for-marker-traits-neg.rs
@@ -0,0 +1,20 @@
+// 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.
+
+#![feature(overlapping_marker_traits)]
+#![feature(optin_builtin_traits)]
+
+// Overlapping negative impls for `MyStruct` are permitted:
+struct MyStruct;
+impl !Send for MyStruct {}
+impl !Send for MyStruct {}
+
+fn main() {
+}
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
index 00000000000..11a46299d8c
--- /dev/null
+++ b/src/test/run-pass/overlap-permitted-for-marker-traits.rs
@@ -0,0 +1,36 @@
+// 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.
+
+// Tests for RFC 1268: we allow overlapping impls of marker traits,
+// that is, traits without items. In this case, a type `T` is
+// `MyMarker` if it is either `Debug` or `Display`.
+
+#![feature(overlapping_marker_traits)]
+#![feature(optin_builtin_traits)]
+
+use std::fmt::{Debug, Display};
+
+trait MyMarker {}
+
+impl<T: Debug> MyMarker for T {}
+impl<T: Display> MyMarker for T {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+    t
+}
+
+fn main() {
+    // Debug && Display:
+    assert_eq!(1, foo(1));
+    assert_eq!(2.0, foo(2.0));
+
+    // Debug && !Display:
+    assert_eq!(vec![1], foo(vec![1]));
+}