Skip to content

Commit d7eb562

Browse files
committed
add test for lattice specialization
1 parent 9196b2d commit d7eb562

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// build-pass
2+
3+
// Check that a reservation impl does not force other impls to follow
4+
// a lattice discipline.
5+
6+
// Why did we ever want to do this?
7+
//
8+
// We want to eventually add a `impl<T> From<!> for T` impl. That impl conflicts
9+
// with existing impls - at least the `impl<T> From<T> for T` impl. There are
10+
// 2 ways we thought of for dealing with that conflict:
11+
//
12+
// 1. Using specialization and doing some handling for the overlap. The current
13+
// thought is for something like "lattice specialization", which means providing
14+
// an (higher-priority) impl for the intersection of every 2 conflicting impls
15+
// that determines what happens in the intersection case. That's the first
16+
// thing we thought about - see e.g.
17+
// https://github.com/rust-lang/rust/issues/57012#issuecomment-452150775
18+
//
19+
// 2. The other way is to notice that `impl From<!> for T` is basically a marker
20+
// trait, as you say since its only method is uninhabited, and allow for "marker
21+
// trait overlap", where the conflict "doesn't matter" as there is nothing that
22+
// can cause a conflict.
23+
//
24+
// Now it turned out lattice specialization doesn't work it, because an
25+
// `impl<T> From<T> for Smaht<T>` would require a `impl From<!> for Smaht<!>`,
26+
// breaking backwards-compatibility in a fairly painful way. So if we want to
27+
// go with a known approach, we should go with a "marker trait overlap"-style
28+
// approach.
29+
30+
#![feature(rustc_attrs, never_type)]
31+
32+
trait MyTrait {}
33+
34+
impl MyTrait for ! {}
35+
36+
trait MyFrom<T> {
37+
fn my_from(x: T) -> Self;
38+
}
39+
40+
// Given the "normal" impls for From
41+
#[rustc_reservation_impl="this impl is reserved"]
42+
impl<T> MyFrom<!> for T {
43+
fn my_from(x: !) -> Self { match x {} }
44+
}
45+
46+
impl<T> MyFrom<T> for T {
47+
fn my_from(x: T) -> Self { x }
48+
}
49+
50+
// ... we *do* want to allow this common pattern, of `From<!> for MySmaht<T>`
51+
struct MySmaht<T>(T);
52+
impl<T> MyFrom<T> for MySmaht<T> {
53+
fn my_from(x: T) -> Self { MySmaht(x) }
54+
}
55+
56+
fn main() {}

0 commit comments

Comments
 (0)