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