Skip to content

Commit 3adcd1c

Browse files
authored
Rollup merge of #41309 - frewsxcv:sg-implement-rfc-1268, r=nikomatsakis
Implement RFC 1268. Rebased version of #40097. Tracking issue: #29864.
2 parents 3f79bdc + ae9f571 commit 3adcd1c

28 files changed

+203
-22
lines changed

src/doc/unstable-book/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
- [optin_builtin_traits](optin-builtin-traits.md)
137137
- [option_entry](option-entry.md)
138138
- [osstring_shrink_to_fit](osstring-shrink-to-fit.md)
139+
- [overlapping_marker_traits](overlapping-marker-traits.md)
139140
- [panic_abort](panic-abort.md)
140141
- [panic_runtime](panic-runtime.md)
141142
- [panic_unwind](panic-unwind.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# `overlapping_marker_traits`
2+
3+
The tracking issue for this feature is: [#29864]
4+
5+
[#29864]: https://github.com/rust-lang/rust/issues/29864
6+
7+
------------------------

src/librustc/traits/select.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1736,7 +1736,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17361736
if other.evaluation == EvaluatedToOk {
17371737
if let ImplCandidate(victim_def) = victim.candidate {
17381738
let tcx = self.tcx().global_tcx();
1739-
return traits::specializes(tcx, other_def, victim_def);
1739+
return traits::specializes(tcx, other_def, victim_def) ||
1740+
tcx.impls_are_allowed_to_overlap(other_def, victim_def);
17401741
}
17411742
}
17421743

src/librustc/traits/specialize/specialization_graph.rs

+4
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

+19
Original file line numberDiff line numberDiff line change
@@ -2227,6 +2227,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
22272227
queries::impl_trait_ref::get(self, DUMMY_SP, id)
22282228
}
22292229

2230+
/// Returns true if the impls are the same polarity and are implementing
2231+
/// a trait which contains no items
2232+
pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
2233+
if !self.sess.features.borrow().overlapping_marker_traits {
2234+
return false;
2235+
}
2236+
let trait1_is_empty = self.impl_trait_ref(def_id1)
2237+
.map_or(false, |trait_ref| {
2238+
self.associated_item_def_ids(trait_ref.def_id).is_empty()
2239+
});
2240+
let trait2_is_empty = self.impl_trait_ref(def_id2)
2241+
.map_or(false, |trait_ref| {
2242+
self.associated_item_def_ids(trait_ref.def_id).is_empty()
2243+
});
2244+
self.trait_impl_polarity(def_id1) == self.trait_impl_polarity(def_id2)
2245+
&& trait1_is_empty
2246+
&& trait2_is_empty
2247+
}
2248+
22302249
// Returns `ty::VariantDef` if `def` refers to a struct,
22312250
// or variant or their constructors, panics otherwise.
22322251
pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {

src/libsyntax/feature_gate.rs

+3
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ declare_features! (
349349

350350
// Allows module-level inline assembly by way of global_asm!()
351351
(active, global_asm, "1.18.0", Some(35119)),
352+
353+
// Allows overlapping impls of marker traits
354+
(active, overlapping_marker_traits, "1.18.0", Some(29864)),
352355
);
353356

354357
declare_features! (

src/test/compile-fail/E0120.rs

+1-1
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

+1
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

+2-1
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

+1-1
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

+1-1
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

+1-1
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

+1
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

+4-4
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<_, _>`:

src/test/compile-fail/coherence-projection-conflict-orphan.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
// due to the orphan rules. Therefore, `A::Item` may yet turn out to
1616
// be `i32`.
1717

18-
pub trait Foo<P> {}
18+
pub trait Foo<P> { fn foo() {} }
1919

2020
pub trait Bar {
2121
type Output: 'static;

src/test/compile-fail/coherence-projection-conflict-ty-param.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
use std::marker::PhantomData;
1515

16-
pub trait Foo<P> {}
16+
pub trait Foo<P> { fn foo() {} }
1717

1818
impl <P, T: Foo<P>> Foo<P> for Option<T> {}
1919

src/test/compile-fail/coherence-projection-conflict.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use std::marker::PhantomData;
1212

13-
pub trait Foo<P> {}
13+
pub trait Foo<P> { fn foo() {} }
1414

1515
pub trait Bar {
1616
type Output: 'static;

src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ extern crate coherence_copy_like_lib as lib;
2020

2121
struct MyType { x: i32 }
2222

23-
trait MyTrait { }
23+
trait MyTrait { fn foo() {} }
2424
impl<T: lib::MyCopy> MyTrait for T { }
2525

2626
// `MyFundamentalStruct` is declared fundamental, so we can test that

src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ extern crate coherence_copy_like_lib as lib;
2020

2121
struct MyType { x: i32 }
2222

23-
trait MyTrait { }
23+
trait MyTrait { fn foo() {} }
2424
impl<T: lib::MyCopy> MyTrait for T { }
2525

2626
// `MyFundamentalStruct` is declared fundamental, so we can test that

src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ extern crate coherence_copy_like_lib as lib;
1919

2020
struct MyType { x: i32 }
2121

22-
trait MyTrait { }
22+
trait MyTrait { fn foo() {} }
2323

2424
impl<T: lib::MyCopy> MyTrait for T { }
2525

src/test/compile-fail/coherence_copy_like_err_struct.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ extern crate coherence_copy_like_lib as lib;
1717

1818
struct MyType { x: i32 }
1919

20-
trait MyTrait { }
20+
trait MyTrait { fn foo() {} }
2121
impl<T: lib::MyCopy> MyTrait for T { }
2222

2323
// `MyStruct` is not declared fundamental, therefore this would

src/test/compile-fail/coherence_copy_like_err_tuple.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ extern crate coherence_copy_like_lib as lib;
1717

1818
struct MyType { x: i32 }
1919

20-
trait MyTrait { }
20+
trait MyTrait { fn foo() {} }
2121
impl<T: lib::MyCopy> MyTrait for T { }
2222

2323
// Tuples are not fundamental, therefore this would require that
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::fmt::{Debug, Display};
12+
13+
trait MyMarker {}
14+
15+
impl<T: Display> MyMarker for T {}
16+
impl<T: Debug> MyMarker for T {}
17+
//~^ ERROR E0119
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test for RFC 1268: we allow overlapping impls of marker traits,
12+
// that is, traits without items. In this case, a type `T` is
13+
// `MyMarker` if it is either `Debug` or `Display`. This test just
14+
// checks that we don't consider **all** types to be `MyMarker`. See
15+
// also the companion test in
16+
// `run-pass/overlap-permitted-for-marker-traits.rs`.
17+
18+
#![feature(overlapping_marker_traits)]
19+
#![feature(optin_builtin_traits)]
20+
21+
use std::fmt::{Debug, Display};
22+
23+
trait Marker {}
24+
25+
impl<T: Debug> Marker for T {}
26+
impl<T: Display> Marker for T {}
27+
28+
fn is_marker<T: Marker>() { }
29+
30+
struct NotDebugOrDisplay;
31+
32+
fn main() {
33+
// Debug && Display:
34+
is_marker::<i32>();
35+
36+
// Debug && !Display:
37+
is_marker::<Vec<i32>>();
38+
39+
// !Debug && !Display
40+
is_marker::<NotDebugOrDisplay>(); //~ ERROR
41+
}

src/test/compile-fail/specialization/specialization-overlap.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@
1010

1111
#![feature(specialization)]
1212

13-
trait Foo {}
13+
trait Foo { fn foo() {} }
1414
impl<T: Clone> Foo for T {}
1515
impl<T> Foo for Vec<T> {} //~ ERROR E0119
1616

17-
trait Bar {}
17+
trait Bar { fn bar() {} }
1818
impl<T> Bar for (T, u8) {}
1919
impl<T> Bar for (u8, T) {} //~ ERROR E0119
2020

21-
trait Baz<U> {}
21+
trait Baz<U> { fn baz() {} }
2222
impl<T> Baz<T> for u8 {}
2323
impl<T> Baz<u8> for T {} //~ ERROR E0119
2424

25-
trait Qux {}
25+
trait Qux { fn qux() {} }
2626
impl<T: Clone> Qux for T {}
2727
impl<T: Eq> Qux for T {} //~ ERROR E0119
2828

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(overlapping_marker_traits)]
12+
#![feature(specialization)]
13+
14+
trait MyMarker {}
15+
16+
impl<T> MyMarker for T {}
17+
impl<T> MyMarker for Vec<T> {}
18+
19+
fn foo<T: MyMarker>(t: T) -> T {
20+
t
21+
}
22+
23+
fn main() {
24+
assert_eq!(1, foo(1));
25+
assert_eq!(2.0, foo(2.0));
26+
assert_eq!(vec![1], foo(vec![1]));
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(overlapping_marker_traits)]
12+
#![feature(optin_builtin_traits)]
13+
14+
// Overlapping negative impls for `MyStruct` are permitted:
15+
struct MyStruct;
16+
impl !Send for MyStruct {}
17+
impl !Send for MyStruct {}
18+
19+
fn main() {
20+
}

0 commit comments

Comments
 (0)