Skip to main content

core_extensions/
type_asserts.rs

1//! Type-level assertions, most useful for tests.
2#![allow(clippy::type_complexity)]
3
4use crate::TypeIdentity;
5
6use std_::marker::PhantomData;
7
8
9/// Asserts that its 2 type parameters are the same type.
10///
11/// This assertion is done on the type level,
12/// so `let _: AssertEq<T, U>;` requires that `T` must be the same type as `U`.
13///
14/// # Example
15///
16/// ```
17/// use core_extensions::type_asserts::AssertEq;
18///
19/// trait ElemTy {
20///     type Elem;
21/// }
22///
23/// impl<A> ElemTy for (A,) {
24///     type Elem = A;
25/// }
26///
27/// let _: AssertEq<u32, <(u32,) as ElemTy>::Elem>;
28///
29/// let _ = AssertEq::new(&0u32, &0u32);
30///
31/// ```
32///
33/// # Non-compiling
34///
35/// ```compile_fail
36/// use core_extensions::type_asserts::AssertEq;
37///
38/// let _: AssertEq<(), u32>;
39/// let _ = AssertEq::new(&(), &0u32);
40///
41/// ```
42///
43/// ```compile_fail
44/// use core_extensions::type_asserts::AssertEq;
45///
46/// let _: AssertEq<u32, ()>;
47/// let _ = AssertEq::new(&0u32, &());
48///
49/// ```
50///
51pub struct AssertEq<L:?Sized,R:?Sized>
52where L:TypeIdentity<Type=R>
53{
54    _marker:PhantomData<(
55        PhantomData<L>,
56        PhantomData<R>,
57    )>,
58}
59
60impl<A> AssertEq<A,A>{
61    /// Constructs an `AssertEq`.
62    pub fn new(_: A, _: A)->Self{
63        Self{_marker: PhantomData}
64    }
65
66    /// Constructs an `AssertEq`.
67    pub const NEW: Self = Self{_marker: PhantomData};
68}
69
70
71/// Asserts that its 3 type parameters are the same type.
72///
73/// This assertion is done on the type level,
74/// so `let _: AssertEq3<A, B, C>;` requires that `A`, `B`, and `C` must be the same type.
75///
76/// # Example
77///
78/// ```
79/// use core_extensions::type_asserts::AssertEq3;
80///
81/// trait TypeParams {
82///     type First;
83///     type Second;
84/// }
85///
86/// impl<A, B> TypeParams for (A, B) {
87///     type First = A;
88///     type Second = B;
89/// }
90///
91/// type First<T> = <T as TypeParams>::First;
92///
93/// type Second<T> = <T as TypeParams>::Second;
94///
95/// let _: AssertEq3<u32, First<(u32, ())>, Second<((), u32)>>;
96///
97/// let _ = AssertEq3::new(&0u32, &0u32, &0u32);
98///
99/// ```
100///
101/// # Non-compiling
102///
103/// ```compile_fail
104/// # use core_extensions::type_asserts::AssertEq3;
105/// let _: AssertEq3<(), u32, u32>;
106/// let _ = AssertEq3::new(&(), &0u32, &0u32);
107/// ```
108///
109/// ```compile_fail
110/// # use core_extensions::type_asserts::AssertEq3;
111/// let _: AssertEq3<u32, (), u32>;
112/// let _ = AssertEq3::new(&0u32, &(), &0u32);
113/// ```
114///
115/// ```compile_fail
116/// # use core_extensions::type_asserts::AssertEq3;
117/// let _: AssertEq3<u32, u32, ()>;
118/// let _ = AssertEq3::new(&0u32, &0u32, &());
119/// ```
120///
121pub struct AssertEq3<A:?Sized,B:?Sized,C:?Sized>
122where 
123    A:TypeIdentity<Type=B>,
124    A:TypeIdentity<Type=C>,
125{
126    _marker:PhantomData<(
127        PhantomData<A>,
128        PhantomData<B>,
129        PhantomData<C>,
130    )>,
131}
132
133impl<A> AssertEq3<A,A,A>{
134    /// Constructs an `AssertEq3`.
135    pub fn new(_: A, _: A, _: A)->Self{
136        Self{_marker: PhantomData}
137    }
138    /// Constructs an `AssertEq3`.
139    pub const NEW: Self = Self{_marker: PhantomData};
140}
141
142
143/// Asserts that its 4 type parameters are the same type.
144///
145/// This assertion is done on the type level,
146/// so `let _: AssertEq4<A, B, C, D>;` requires that 
147/// `A`, `B`, `C`, and `D` must be the same type.
148///
149/// # Example
150///
151/// ```
152/// use core_extensions::type_asserts::AssertEq4;
153///
154/// trait TypeParams {
155///     type First;
156///     type Second;
157///     type Third;
158/// }
159///
160/// impl<A, B, C> TypeParams for (A, B, C) {
161///     type First = A;
162///     type Second = B;
163///     type Third = C;
164/// }
165///
166/// type First<T> = <T as TypeParams>::First;
167///
168/// type Second<T> = <T as TypeParams>::Second;
169///
170/// type Third<T> = <T as TypeParams>::Third;
171///
172/// let _: AssertEq4<
173///     u32,
174///     First <(u32, (), ())>,
175///     Second<((), u32, ())>,
176///     Third <((), (), u32)>,
177/// >;
178///
179/// let _ = AssertEq4::new(&0u32, &0u32, &0u32, &0u32);
180///
181/// ```
182///
183/// # Non-compiling
184///
185/// ```compile_fail
186/// # use core_extensions::type_asserts::AssertEq4;
187/// let _: AssertEq4<(), u32, u32, u32>;
188/// let _ = AssertEq4::new(&(), &0u32, &0u32, &0u32);
189/// ```
190///
191/// ```compile_fail
192/// # use core_extensions::type_asserts::AssertEq4;
193/// let _: AssertEq4<u32, (), u32, u32>;
194/// let _ = AssertEq4::new(&0u32, &(), &0u32, &0u32);
195/// ```
196///
197/// ```compile_fail
198/// # use core_extensions::type_asserts::AssertEq4;
199/// let _: AssertEq4<u32, u32, (), u32>;
200/// let _ = AssertEq4::new(&0u32, &0u32, &(), &0u32);
201/// ```
202///
203/// ```compile_fail
204/// # use core_extensions::type_asserts::AssertEq4;
205/// let _: AssertEq4<u32, u32, u32, ()>;
206/// let _ = AssertEq4::new(&0u32, &0u32, &0u32, &());
207/// ```
208///
209pub struct AssertEq4<A:?Sized,B:?Sized,C:?Sized,D:?Sized>
210where 
211    A:TypeIdentity<Type=B>,
212    A:TypeIdentity<Type=C>,
213    A:TypeIdentity<Type=D>,
214{
215    _marker:PhantomData<(
216        PhantomData<A>,
217        PhantomData<B>,
218        PhantomData<C>,
219        PhantomData<D>,
220    )>,
221}
222
223impl<A> AssertEq4<A,A,A,A>{
224    /// Constructs an `AssertEq4`.
225    pub fn new(_: A, _: A, _: A, _: A)->Self{
226        Self{_marker: PhantomData}
227    }
228    
229    /// Constructs an `AssertEq4`.
230    pub const NEW: Self = Self{_marker: PhantomData};
231}
232
233
234////////////////////////////////////////////////////////////////////////////////
235