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]
47macro_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]
93macro_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