From 4aca54001865435c799757c6fcb8595c23ff6c77 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Sat, 25 Feb 2017 16:16:27 -0500 Subject: [PATCH 1/7] 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 #29864 --- src/librustc/traits/specialize/mod.rs | 5 ++++ .../traits/specialize/specialization_graph.rs | 5 ++++ src/librustc/ty/mod.rs | 10 ++++++++ src/test/compile-fail/E0120.rs | 2 +- ...herence-conflicting-negative-trait-impl.rs | 2 +- .../coherence-default-trait-impl.rs | 2 +- src/test/compile-fail/coherence-impls-send.rs | 1 - .../coherence-no-direct-lifetime-dispatch.rs | 2 +- .../coherence-overlap-all-t-and-tuple.rs | 1 + .../coherence-overlap-messages.rs | 8 +++---- .../coherence-projection-conflict-orphan.rs | 2 +- .../coherence-projection-conflict-ty-param.rs | 2 +- .../coherence-projection-conflict.rs | 2 +- ...erence_copy_like_err_fundamental_struct.rs | 2 +- ...ce_copy_like_err_fundamental_struct_ref.rs | 2 +- ..._copy_like_err_fundamental_struct_tuple.rs | 2 +- .../coherence_copy_like_err_struct.rs | 2 +- .../coherence_copy_like_err_tuple.rs | 2 +- .../specialization/specialization-overlap.rs | 8 +++---- .../overlap-permitted-for-marker-traits.rs | 23 +++++++++++++++++++ 20 files changed, 64 insertions(+), 21 deletions(-) create mode 100644 src/test/run-pass/overlap-permitted-for-marker-traits.rs diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 50a4d982832ac..6455de48a299d 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -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 && diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 40eb69395678f..87abe681d3938 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -113,6 +113,11 @@ impl<'a, 'gcx, 'tcx> Children { 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); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8ff91583d0822..9fdabd38d4ab4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2227,6 +2227,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { 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 { diff --git a/src/test/compile-fail/E0120.rs b/src/test/compile-fail/E0120.rs index 3fdeb75317540..80cc0d2680f7c 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/coherence-conflicting-negative-trait-impl.rs b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs index 7fd1b17f2966c..d841e8c41d984 100644 --- a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs +++ b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs @@ -20,8 +20,8 @@ impl !Send for TestType {} //~^ ERROR conflicting implementations of trait `std::marker::Send` unsafe impl Send for TestType {} -//~^ ERROR conflicting implementations of trait `std::marker::Send` impl !Send for TestType {} +//~^ 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 15a80c64f8b06..e6bf068156c2b 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 f130a9353516f..d0e6bc6a1c699 100644 --- a/src/test/compile-fail/coherence-impls-send.rs +++ b/src/test/compile-fail/coherence-impls-send.rs @@ -34,7 +34,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 6de338f1db0fa..47026cd32d411 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 MyTrait for T {} impl 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 928ba7a36db26..1fad608db6c3b 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 { + fn foo() {} } impl From for T { diff --git a/src/test/compile-fail/coherence-overlap-messages.rs b/src/test/compile-fail/coherence-overlap-messages.rs index 0ae8135221c21..a10deeafbe67e 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 Foo for T {} impl Foo for U {} //~ ERROR conflicting implementations of trait `Foo`: -trait Bar {} +trait Bar { fn bar() {} } impl Bar for (T, u8) {} impl Bar for (u8, T) {} //~ ERROR conflicting implementations of trait `Bar` for type `(u8, u8)`: -trait Baz {} +trait Baz { fn baz() {} } impl Baz for T {} impl Baz for u8 {} //~ ERROR conflicting implementations of trait `Baz` for type `u8`: -trait Quux {} +trait Quux { fn quux() {} } impl Quux for T {} impl Quux 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 3ed3549de89aa..784ff0cd5e0aa 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

{} +pub trait Foo

{ 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 f04902a70f68c..120d9046389a1 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

{} +pub trait Foo

{ fn foo() {} } impl > Foo

for Option {} diff --git a/src/test/compile-fail/coherence-projection-conflict.rs b/src/test/compile-fail/coherence-projection-conflict.rs index 6d3ab32f06f43..3c32ab38b93dc 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

{} +pub trait Foo

{ 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 fcd6e5c495207..9fbb7aa4cb1a7 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 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 b5c0a7fb5f564..2f6dca4f3c271 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 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 8e3e3f31cb5f1..f424e8872010f 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 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 35bc17b8e8870..04262e65c5a2a 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 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 a70cc92955fb0..378a70864f0ee 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 MyTrait for T { } // Tuples are not fundamental, therefore this would require that diff --git a/src/test/compile-fail/specialization/specialization-overlap.rs b/src/test/compile-fail/specialization/specialization-overlap.rs index f579817100107..ff12a82db5b7d 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 Foo for T {} impl Foo for Vec {} //~ ERROR E0119 -trait Bar {} +trait Bar { fn bar() {} } impl Bar for (T, u8) {} impl Bar for (u8, T) {} //~ ERROR E0119 -trait Baz {} +trait Baz { fn baz() {} } impl Baz for u8 {} impl Baz for T {} //~ ERROR E0119 -trait Qux {} +trait Qux { fn qux() {} } impl Qux for T {} impl 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 index 0000000000000..66c45e6718331 --- /dev/null +++ b/src/test/run-pass/overlap-permitted-for-marker-traits.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait MyMarker {} + +impl MyMarker for T {} +impl MyMarker for T {} + +fn foo(t: T) -> T { + t +} + +fn main() { + assert_eq!(1, foo(1)); + assert_eq!(vec![1], foo(vec![1])); +} From ddcca79d25fffd6604fba593b1ca642a9dfa5727 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 3 Mar 2017 09:09:09 -0500 Subject: [PATCH 2/7] Update with response to feedback --- src/librustc/ty/mod.rs | 2 +- src/test/run-pass/overlap-permitted-for-marker-traits.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9fdabd38d4ab4..e9bcb80cff25e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2227,7 +2227,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { queries::impl_trait_ref::get(self, DUMMY_SP, id) } - /// Returns true if the impl is positive and is for a triat which contains + /// Returns true if the impl is positive and is for a trait 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 diff --git a/src/test/run-pass/overlap-permitted-for-marker-traits.rs b/src/test/run-pass/overlap-permitted-for-marker-traits.rs index 66c45e6718331..b0b1930d274d6 100644 --- a/src/test/run-pass/overlap-permitted-for-marker-traits.rs +++ b/src/test/run-pass/overlap-permitted-for-marker-traits.rs @@ -19,5 +19,6 @@ fn foo(t: T) -> T { fn main() { assert_eq!(1, foo(1)); + assert_eq!(2.0, foo(2.0)); assert_eq!(vec![1], foo(vec![1])); } From c81c958e984b92222909e2ba5c74a2260a44bdae Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 17 Mar 2017 12:43:15 -0400 Subject: [PATCH 3/7] Further update with response to feedback --- src/librustc/traits/select.rs | 3 ++- src/librustc/traits/specialize/mod.rs | 5 ----- .../traits/specialize/specialization_graph.rs | 5 ++--- src/librustc/ty/mod.rs | 22 ++++++++++++------- .../auxiliary/trait_impl_conflict.rs | 1 + 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 67d50210ba39a..410eb2b84849e 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/mod.rs b/src/librustc/traits/specialize/mod.rs index 6455de48a299d..50a4d982832ac 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -155,11 +155,6 @@ 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 && diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 87abe681d3938..6e2c16c82aeb4 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -113,9 +113,8 @@ impl<'a, 'gcx, 'tcx> Children { 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)); + 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); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e9bcb80cff25e..2ae77046a90ed 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2227,14 +2227,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { queries::impl_trait_ref::get(self, DUMMY_SP, id) } - /// Returns true if the impl is positive and is for a trait 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 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 { + 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, diff --git a/src/test/compile-fail/auxiliary/trait_impl_conflict.rs b/src/test/compile-fail/auxiliary/trait_impl_conflict.rs index c3ecbb014dc6b..3190ce430ad67 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 { From adcdd605be9cbdb338d4ecc2410cde87272f2191 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 17 Mar 2017 14:16:29 -0400 Subject: [PATCH 4/7] Put overlapping impls behind feature gate, add tests I've added some explicit tests that negative impls are allowed to overlap, and also to make sure that the feature doesn't interfere with specialization. I've not added an explicit test for positive overlapping with negative, as that's already tested elsewhere. --- src/librustc/ty/mod.rs | 3 +++ src/libsyntax/feature_gate.rs | 3 +++ ...herence-conflicting-negative-trait-impl.rs | 1 + src/test/compile-fail/coherence-impls-send.rs | 1 + ...overlapping-impls-requires-feature-gate.rs | 17 ++++++++++++ ...lap-doesnt-conflict-with-specialization.rs | 27 +++++++++++++++++++ .../overlap-permitted-for-marker-traits.rs | 7 +++++ 7 files changed, 59 insertions(+) create mode 100644 src/test/compile-fail/overlapping-impls-requires-feature-gate.rs create mode 100644 src/test/run-pass/overlap-doesnt-conflict-with-specialization.rs diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2ae77046a90ed..3da9383762bc6 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2230,6 +2230,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// 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() diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 8b62416dcbdbd..6e455234196d4 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/coherence-conflicting-negative-trait-impl.rs b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs index d841e8c41d984..8e9d1eff34580 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 {} diff --git a/src/test/compile-fail/coherence-impls-send.rs b/src/test/compile-fail/coherence-impls-send.rs index d0e6bc6a1c699..9caaee41aeb1d 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; diff --git a/src/test/compile-fail/overlapping-impls-requires-feature-gate.rs b/src/test/compile-fail/overlapping-impls-requires-feature-gate.rs new file mode 100644 index 0000000000000..bf2b06dd8ba0c --- /dev/null +++ b/src/test/compile-fail/overlapping-impls-requires-feature-gate.rs @@ -0,0 +1,17 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait MyMarker {} + +impl MyMarker for T {} +impl MyMarker for Vec {} +//~^ ERROR E0119 + +fn main() {} 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 0000000000000..ed45d81c0d6a1 --- /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 or the MIT license +// , 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 MyMarker for T {} +impl MyMarker for Vec {} + +fn foo(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.rs b/src/test/run-pass/overlap-permitted-for-marker-traits.rs index b0b1930d274d6..45085c093fc98 100644 --- a/src/test/run-pass/overlap-permitted-for-marker-traits.rs +++ b/src/test/run-pass/overlap-permitted-for-marker-traits.rs @@ -8,11 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(overlapping_marker_traits)] +#![feature(optin_builtin_traits)] + trait MyMarker {} impl MyMarker for T {} impl MyMarker for T {} +struct MyStruct; +impl !Send for MyStruct {} +impl !Send for MyStruct {} + fn foo(t: T) -> T { t } From 5a9c25b91e3ccefbeb52b1bd0a79ed48d9efae85 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 17 Mar 2017 19:20:18 -0400 Subject: [PATCH 5/7] Name files what tidy wants them to be namd --- ...-feature-gate.rs => feature-gate-overlapping_marker_traits.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/compile-fail/{overlapping-impls-requires-feature-gate.rs => feature-gate-overlapping_marker_traits.rs} (100%) diff --git a/src/test/compile-fail/overlapping-impls-requires-feature-gate.rs b/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs similarity index 100% rename from src/test/compile-fail/overlapping-impls-requires-feature-gate.rs rename to src/test/compile-fail/feature-gate-overlapping_marker_traits.rs From 805704c3469853b923c61744eed64a79c7879170 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 30 Mar 2017 08:54:28 -0400 Subject: [PATCH 6/7] update tests slightly --- .../feature-gate-overlapping_marker_traits.rs | 6 ++- src/test/compile-fail/overlap-marker-trait.rs | 41 +++++++++++++++++++ ...overlap-permitted-for-marker-traits-neg.rs | 20 +++++++++ .../overlap-permitted-for-marker-traits.rs | 17 +++++--- 4 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 src/test/compile-fail/overlap-marker-trait.rs create mode 100644 src/test/run-pass/overlap-permitted-for-marker-traits-neg.rs diff --git a/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs b/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs index bf2b06dd8ba0c..d2aa4e59b5ba9 100644 --- a/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs +++ b/src/test/compile-fail/feature-gate-overlapping_marker_traits.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::fmt::{Debug, Display}; + trait MyMarker {} -impl MyMarker for T {} -impl MyMarker for Vec {} +impl MyMarker for T {} +impl 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 0000000000000..a649ae25f34ea --- /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 or the MIT license +// , 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 Marker for T {} +impl Marker for T {} + +fn is_marker() { } + +struct NotDebugOrDisplay; + +fn main() { + // Debug && Display: + is_marker::(); + + // Debug && !Display: + is_marker::>(); + + // !Debug && !Display + is_marker::(); //~ ERROR +} 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 0000000000000..740d5d22ab507 --- /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 or the MIT license +// , 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 index 45085c093fc98..11a46299d8c83 100644 --- a/src/test/run-pass/overlap-permitted-for-marker-traits.rs +++ b/src/test/run-pass/overlap-permitted-for-marker-traits.rs @@ -8,24 +8,29 @@ // 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)] -trait MyMarker {} +use std::fmt::{Debug, Display}; -impl MyMarker for T {} -impl MyMarker for T {} +trait MyMarker {} -struct MyStruct; -impl !Send for MyStruct {} -impl !Send for MyStruct {} +impl MyMarker for T {} +impl MyMarker for T {} fn foo(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])); } From ae9f571cd11d0b822827547ca6fe192cabb55d0d Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Fri, 14 Apr 2017 20:38:10 -0400 Subject: [PATCH 7/7] Add Unstable Book entry for 'overlapping-marker-traits'. --- src/doc/unstable-book/src/SUMMARY.md | 1 + src/doc/unstable-book/src/overlapping-marker-traits.md | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 src/doc/unstable-book/src/overlapping-marker-traits.md diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index a5599395f7965..a9796fdf01e0d 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 0000000000000..a4920839c6ca9 --- /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 + +------------------------