]>
Commit | Line | Data |
---|---|---|
e74abb32 XL |
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 | // | |
94222f64 | 8 | // We want to eventually add an `impl<T> From<!> for T` impl. That impl conflicts |
e74abb32 XL |
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 | |
13 | // overlap. The current thought is to require ["intersection | |
14 | // impls"][ii], specialization", which means providing an | |
15 | // (higher-priority) impl for the intersection of every 2 conflicting | |
16 | // impls that determines what happens in the intersection case. That's | |
17 | // the first thing we thought about - see e.g. | |
18 | // https://github.com/rust-lang/rust/issues/57012#issuecomment-452150775 | |
19 | // | |
20 | // 2. The other way is to notice that `impl From<!> for T` is basically a | |
21 | // marker trait since its only method is uninhabited, and allow for "marker | |
22 | // trait overlap", where the conflict "doesn't matter" because it can't | |
23 | // actually cause any ambiguity. | |
24 | // | |
25 | // Now it turned out lattice specialization doesn't work it, because an | |
94222f64 | 26 | // `impl<T> From<T> for Smaht<T>` would require an `impl From<!> for Smaht<!>`, |
e74abb32 XL |
27 | // breaking backwards-compatibility in a fairly painful way. So if we want to |
28 | // go with a known approach, we should go with a "marker trait overlap"-style | |
29 | // approach. | |
30 | // | |
136023e0 | 31 | // [ii]: https://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/ |
e74abb32 XL |
32 | |
33 | #![feature(rustc_attrs, never_type)] | |
34 | ||
35 | trait MyTrait {} | |
36 | ||
37 | impl MyTrait for ! {} | |
38 | ||
39 | trait MyFrom<T> { | |
40 | fn my_from(x: T) -> Self; | |
41 | } | |
42 | ||
43 | // Given the "normal" impls for From | |
44 | #[rustc_reservation_impl="this impl is reserved"] | |
45 | impl<T> MyFrom<!> for T { | |
46 | fn my_from(x: !) -> Self { match x {} } | |
47 | } | |
48 | ||
49 | impl<T> MyFrom<T> for T { | |
50 | fn my_from(x: T) -> Self { x } | |
51 | } | |
52 | ||
53 | // ... we *do* want to allow this common pattern, of `From<!> for MySmaht<T>` | |
54 | struct MySmaht<T>(T); | |
55 | impl<T> MyFrom<T> for MySmaht<T> { | |
56 | fn my_from(x: T) -> Self { MySmaht(x) } | |
57 | } | |
58 | ||
59 | fn main() {} |