1 | /// Asserts that _all_ types in a list are equal to each other. |
2 | /// |
3 | /// # Examples |
4 | /// |
5 | /// Often times, type aliases are used to express usage semantics via naming. In |
6 | /// some cases, the underlying type may differ based on platform. However, other |
7 | /// types like [`c_float`] will always alias the same type. |
8 | /// |
9 | /// ``` |
10 | /// # #[macro_use ] extern crate static_assertions; fn main() {} |
11 | /// use std::os::raw::c_float; |
12 | /// |
13 | /// assert_type_eq_all!(c_float, f32); |
14 | /// ``` |
15 | /// |
16 | /// This macro can also be used to compare types that involve lifetimes! Just |
17 | /// use `'static` in that case: |
18 | /// |
19 | /// ``` |
20 | /// # #[macro_use ] extern crate static_assertions; |
21 | /// # fn main() { |
22 | /// type Buf<'a> = &'a [u8]; |
23 | /// |
24 | /// assert_type_eq_all!(Buf<'static>, &'static [u8]); |
25 | /// # } |
26 | /// ``` |
27 | /// |
28 | /// The following example fails to compile because `String` and `str` do not |
29 | /// refer to the same type: |
30 | /// |
31 | /// ```compile_fail |
32 | /// # #[macro_use ] extern crate static_assertions; fn main() {} |
33 | /// assert_type_eq_all!(String, str); |
34 | /// ``` |
35 | /// |
36 | /// This should also work the other way around, regardless of [`Deref`] |
37 | /// implementations. |
38 | /// |
39 | /// ```compile_fail |
40 | /// # #[macro_use ] extern crate static_assertions; fn main() {} |
41 | /// assert_type_eq_all!(str, String); |
42 | /// ``` |
43 | /// |
44 | /// [`c_float`]: https://doc.rust-lang.org/std/os/raw/type.c_float.html |
45 | /// [`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html |
46 | #[macro_export ] |
47 | macro_rules! assert_type_eq_all { |
48 | ($x:ty, $($xs:ty),+ $(,)*) => { |
49 | const _: fn() = || { $({ |
50 | trait TypeEq { |
51 | type This: ?Sized; |
52 | } |
53 | |
54 | impl<T: ?Sized> TypeEq for T { |
55 | type This = Self; |
56 | } |
57 | |
58 | fn assert_type_eq_all<T, U>() |
59 | where |
60 | T: ?Sized + TypeEq<This = U>, |
61 | U: ?Sized, |
62 | {} |
63 | |
64 | assert_type_eq_all::<$x, $xs>(); |
65 | })+ }; |
66 | }; |
67 | } |
68 | |
69 | /// Asserts that _all_ types are **not** equal to each other. |
70 | /// |
71 | /// # Examples |
72 | /// |
73 | /// Rust has all sorts of slices, but they represent different types of data: |
74 | /// |
75 | /// ``` |
76 | /// # #[macro_use ] extern crate static_assertions; fn main() {} |
77 | /// assert_type_ne_all!([u8], [u16], str); |
78 | /// ``` |
79 | /// |
80 | /// The following example fails to compile because [`c_uchar`] is a type alias |
81 | /// for [`u8`]: |
82 | /// |
83 | /// ```compile_fail |
84 | /// # #[macro_use ] extern crate static_assertions; fn main() {} |
85 | /// use std::os::raw::c_uchar; |
86 | /// |
87 | /// assert_type_ne_all!(c_uchar, u8, u32); |
88 | /// ``` |
89 | /// |
90 | /// [`c_uchar`]: https://doc.rust-lang.org/std/os/raw/type.c_uchar.html |
91 | /// [`u8`]: https://doc.rust-lang.org/std/primitive.u8.html |
92 | #[macro_export ] |
93 | macro_rules! assert_type_ne_all { |
94 | ($x:ty, $($y:ty),+ $(,)?) => { |
95 | const _: fn() = || { |
96 | trait MutuallyExclusive {} |
97 | impl MutuallyExclusive for $x {} |
98 | $(impl MutuallyExclusive for $y {})+ |
99 | }; |
100 | }; |
101 | } |
102 | |