const_format/macros/assertions/assertc_macros.rs
1macro_rules! with_shared_docs {(
2 $(#[$before_clarification:meta])*
3 ;clarification
4 $(#[$before_syntax:meta])*
5 ;syntax
6 $(#[$after_syntax:meta])*
7 ;error_message
8 $(#[$after_error_message:meta])*
9 ;limitations
10 $item:item
11) => (
12 $(#[$before_clarification])*
13 ///
14 /// This macro requires the `"assertc"` feature to be exported.
15 ///
16 $(#[$before_syntax])*
17 ///
18 /// This macro uses [the same syntax](./fmt/index.html#fmtsyntax)
19 /// for the format string and supports the same formatting arguments as the
20 /// [`formatc`] macro.
21 ///
22 $(#[$after_syntax])*
23 $(#[$after_error_message])*
24 /// # Limitations
25 ///
26 /// This macro has these limitations:
27 ///
28 /// - It can only use constants that involve concrete types,
29 /// so while a `Type::<u8>::FOO` in an argument would be fine,
30 /// `Type::<T>::FOO` would not be (`T` being a type parameter).
31 ///
32 /// - Integer arguments must have a type inferrable from context,
33 /// [as described in the integer arguments section in the root module
34 /// ](./index.html#integer-args).
35 ///
36 /// [`PWrapper`]: ./struct.PWrapper.html
37 /// [`formatc`]: ./macro.formatc.html
38 /// [`FormatMarker`]: ./marker_traits/trait.FormatMarker.html
39 ///
40 $item
41)}
42
43////////////////////////////////////////////////////////////////////////////////
44
45with_shared_docs! {
46 /// Compile-time assertions with formatting.
47 ///
48 ;clarification
49 ;syntax
50 ;error_message
51 ;limitations
52 ///
53 /// # Examples
54 ///
55 /// ### Passing assertion
56 ///
57 /// ```rust
58 ///
59 /// use const_format::assertc;
60 ///
61 /// use std::mem::size_of;
62 ///
63 /// assertc!(
64 /// size_of::<&str>() == size_of::<&[u8]>(),
65 /// "The size of `&str`({} bytes) and `&[u8]`({} bytes) aren't the same?!?!",
66 /// size_of::<&str>(),
67 /// size_of::<&[u8]>(),
68 /// );
69 ///
70 /// # fn main(){}
71 /// ```
72 ///
73 /// ### Failing assertion
74 ///
75 /// This example demonstrates a failing assertion,
76 /// and how the compiler error looks like as of 2023-10-14.
77 ///
78 /// ```compile_fail
79 ///
80 /// use const_format::assertc;
81 ///
82 /// const L: u64 = 2;
83 /// const R: u64 = 2;
84 ///
85 /// assertc!(L + R == 5, "{} plus {} isn't 5, buddy", L, R);
86 ///
87 /// # fn main(){}
88 /// ```
89 ///
90 /// This is the compiler output:
91 ///
92 /// ```text
93 /// error[E0080]: evaluation of constant value failed
94 /// --> const_format/src/macros/assertions/assertc_macros.rs:109:10
95 /// |
96 /// 11 | assertc!(L + R == 5, "{} plus {} isn't 5, buddy", L, R);
97 /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at '
98 /// assertion failed.
99 /// 2 plus 2 isn't 5, buddy
100 /// ', const_format/src/macros/assertions/assertc_macros.rs:11:10
101 /// ```
102 ///
103 #[cfg_attr(feature = "__docsrs", doc(cfg(feature = "assertc")))]
104 #[macro_export]
105 macro_rules! assertc {
106 ($($parameters:tt)*) => (
107 $crate::__assertc_inner!{
108 __formatc_if_impl
109 ($($parameters)*)
110 ($($parameters)*)
111 }
112 );
113 }
114}
115
116////////////////////////////////////////////////////////////////////////////////
117
118macro_rules! assert_eq_docs {
119 (
120 $(#[$documentation:meta])*
121 ;documentation
122 $item:item
123 ) => (
124 with_shared_docs! {
125 $(#[$documentation])*
126 ;clarification
127 /// # Arguments
128 ///
129 /// This macro accepts these types for comparison and debug printing:
130 ///
131 /// - Standard library types for which [`PWrapper`] wrapping that type
132 /// has a `const_eq` method.
133 /// This includes all integer types, `&str`, slices/arrays of integers/`&str`,
134 /// Options of integers/`&str`, etc.
135 ///
136 /// - non-standard-library types that implement [`FormatMarker`] with debug formatting<br>
137 /// and have a `const fn const_eq(&self, other:&Self) -> bool` inherent method,
138 ///
139 ;syntax
140 ;error_message
141 ;limitations
142 $item
143 }
144 )
145}
146
147assert_eq_docs! {
148 /// Compile-time equality assertion with formatting.
149 ///
150 ;documentation
151 ///
152 /// # Examples
153 ///
154 /// ### Passing assertion
155 ///
156 /// ```rust
157 ///
158 /// use const_format::assertc_eq;
159 ///
160 /// use std::mem::size_of;
161 ///
162 /// assertc_eq!(size_of::<usize>(), size_of::<[usize;1]>());
163 ///
164 /// const TWO: u32 = 2;
165 /// assertc_eq!(TWO, TWO, "Oh no {} doesn't equal itself!!", TWO);
166 ///
167 /// # fn main(){}
168 /// ```
169 ///
170 /// ### Failing assertion
171 ///
172 /// This example demonstrates a failing assertion,
173 /// and how the compiler error looks like as of 2023-10-14.
174 ///
175 /// ```compile_fail
176 ///
177 /// use const_format::assertc_eq;
178 ///
179 /// use std::mem::size_of;
180 ///
181 /// assertc_eq!(size_of::<u32>(), size_of::<u8>());
182 ///
183 /// # fn main(){}
184 /// ```
185 ///
186 /// This is the compiler output:
187 ///
188 /// ```text
189 /// error[E0080]: evaluation of constant value failed
190 /// --> const_format/src/macros/assertions/assertc_macros.rs:222:13
191 /// |
192 /// 10 | assertc_eq!(size_of::<u32>(), size_of::<u8>());
193 /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at '
194 /// assertion failed: `(left == right)`
195 /// left: `4`
196 /// right: `1`', const_format/src/macros/assertions/assertc_macros.rs:10:13
197 /// ```
198 ///
199 /// ### Comparing user-defined types
200 ///
201 /// This example demonstrates how you can assert that two values of a
202 /// user-defined type are equal.
203 ///
204 #[cfg_attr(feature = "derive", doc = "```compile_fail")]
205 #[cfg_attr(not(feature = "derive"), doc = "```ignore")]
206 ///
207 /// use const_format::{Formatter, PWrapper};
208 /// use const_format::{ConstDebug, assertc_eq, try_};
209 ///
210 /// const POINT: Point = Point{ x: 5, y: 8, z: 13 };
211 /// const OTHER_POINT: Point = Point{ x: 21, y: 34, z: 55 };
212 ///
213 /// assertc_eq!(POINT, OTHER_POINT);
214 ///
215 /// #[derive(ConstDebug)]
216 /// pub struct Point {
217 /// pub x: u32,
218 /// pub y: u32,
219 /// pub z: u32,
220 /// }
221 ///
222 /// impl Point {
223 /// pub const fn const_eq(&self, other: &Self) -> bool {
224 /// self.x == other.x &&
225 /// self.y == other.y &&
226 /// self.z == other.z
227 /// }
228 /// }
229 /// ```
230 ///
231 /// This is the compiler output:
232 ///
233 /// ```text
234 /// error[E0080]: evaluation of constant value failed
235 /// --> src/macros/assertions.rs:331:14
236 /// |
237 /// 12 | assertc_eq!(POINT, OTHER_POINT);
238 /// | ^^^^^^^^^^^^^^^^^^ the evaluated program panicked at '
239 /// assertion failed: `(left == right)`
240 /// left: `Point {
241 /// x: 5,
242 /// y: 8,
243 /// z: 13,
244 /// }`
245 /// right: `Point {
246 /// x: 21,
247 /// y: 34,
248 /// z: 55,
249 /// }`', src/macros/assertions.rs:12:14
250 ///
251 /// error: aborting due to previous error
252 ///
253 /// ```
254 ///
255 #[cfg_attr(feature = "__docsrs", doc(cfg(feature = "assertc")))]
256 #[macro_export]
257 macro_rules! assertc_eq {
258 ($($parameters:tt)*) => (
259 $crate::__assertc_equality_inner!{
260 ($($parameters)*)
261 ($($parameters)*)
262 ( == )
263 ("==")
264 }
265 );
266 }
267}
268
269assert_eq_docs! {
270 /// Compile-time inequality assertion with formatting.
271 ///
272 ;documentation
273 ///
274 /// # Examples
275 ///
276 /// ### Passing assertion
277 ///
278 /// ```rust
279 ///
280 /// use const_format::assertc_ne;
281 ///
282 /// use std::mem::size_of;
283 ///
284 /// assertc_ne!(size_of::<u32>(), size_of::<[u32; 2]>());
285 ///
286 /// const TWO: u32 = 2;
287 /// const THREE: u32 = 3;
288 /// assertc_ne!(TWO, THREE, "Oh no {} somehow equals {}!!", TWO, THREE);
289 ///
290 /// # fn main(){}
291 /// ```
292 ///
293 /// ### Failing assertion
294 ///
295 /// This example demonstrates a failing assertion,
296 /// and how the compiler error looks like as of 2023-10-14.
297 ///
298 /// ```compile_fail
299 ///
300 /// use const_format::assertc_ne;
301 ///
302 /// use std::mem::size_of;
303 ///
304 /// type Foo = u32;
305 ///
306 /// assertc_ne!(size_of::<u32>(), size_of::<Foo>());
307 ///
308 /// # fn main(){}
309 /// ```
310 ///
311 /// This is the compiler output:
312 ///
313 /// ```text
314 /// error[E0080]: evaluation of constant value failed
315 /// --> const_format/src/macros/assertions/assertc_macros.rs:350:13
316 /// |
317 /// 12 | assertc_ne!(size_of::<u32>(), size_of::<Foo>());
318 /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at '
319 /// assertion failed: `(left != right)`
320 /// left: `4`
321 /// right: `4`', const_format/src/macros/assertions/assertc_macros.rs:12:13
322 /// ```
323 ///
324 /// ### Comparing user-defined types
325 ///
326 /// This example demonstrates how you can assert that two values of a
327 /// user-defined type are unequal.
328 ///
329 #[cfg_attr(feature = "derive", doc = "```compile_fail")]
330 #[cfg_attr(not(feature = "derive"), doc = "```ignore")]
331 ///
332 /// use const_format::{Formatter, PWrapper};
333 /// use const_format::{ConstDebug, assertc_ne, try_};
334 ///
335 /// const POINT: Point = Point{ x: 5, y: 8, z: 13 };
336 ///
337 /// assertc_ne!(POINT, POINT);
338 ///
339 /// #[derive(ConstDebug)]
340 /// pub struct Point {
341 /// pub x: u32,
342 /// pub y: u32,
343 /// pub z: u32,
344 /// }
345 ///
346 /// impl Point {
347 /// pub const fn const_eq(&self, other: &Self) -> bool {
348 /// self.x == other.x &&
349 /// self.y == other.y &&
350 /// self.z == other.z
351 /// }
352 /// }
353 /// ```
354 ///
355 /// This is the compiler output:
356 ///
357 /// ```text
358 /// error[E0080]: evaluation of constant value failed
359 /// --> src/macros/assertions.rs:451:14
360 /// |
361 /// 11 | assertc_ne!(POINT, POINT);
362 /// | ^^^^^^^^^^^^ the evaluated program panicked at '
363 /// assertion failed: `(left != right)`
364 /// left: `Point {
365 /// x: 5,
366 /// y: 8,
367 /// z: 13,
368 /// }`
369 /// right: `Point {
370 /// x: 5,
371 /// y: 8,
372 /// z: 13,
373 /// }`', src/macros/assertions.rs:11:14
374 ///
375 /// error: aborting due to previous error
376 ///
377 /// ```
378 ///
379 #[cfg_attr(feature = "__docsrs", doc(cfg(feature = "assertc")))]
380 #[macro_export]
381 macro_rules! assertc_ne {
382 ($($parameters:tt)*) => (
383 $crate::__assertc_equality_inner!{
384 ($($parameters)*)
385 ($($parameters)*)
386 ( != )
387 ("!=")
388 }
389 );
390 }
391}
392
393#[doc(hidden)]
394#[macro_export]
395macro_rules! __assertc_equality_inner {
396 (
397 ($($parameters:tt)*)
398 (
399 $left:expr,
400 $right:expr
401 $(, $fmt_literal:expr $(,$fmt_arg:expr)*)? $(,)?
402 )
403 ($($op:tt)*)
404 ($op_str:expr)
405 )=>{
406 const _: () = {
407 use $crate::__cf_osRcTFl4A;
408 use $crate::pmr::respan_to as __cf_respan_to;
409
410 const LEFT: $crate::pmr::bool = {
411 // Have to use `respan_to` to make the `multiple coerce found` error
412 // point at the `$left` argument here.
413 use $crate::coerce_to_fmt as __cf_coerce_to_fmt;
414 match [&$left, &$right] {
415 __cf_respan_to!(($left) [left, right]) =>
416 __cf_respan_to!(($left) __cf_coerce_to_fmt!(left).const_eq(right)),
417 }
418 };
419 const RIGHT: $crate::pmr::bool = true;
420
421 $crate::__assertc_common!{
422 __formatc_if_impl
423 ($($parameters)*)
424 (LEFT $($op)* RIGHT)
425 (
426 concat!(
427 "\nassertion failed: `(left ",
428 $op_str,
429 " right)`\n",
430 " left: `{left_NHPMWYD3NJA:#?}`\n\
431 right: `{right_NHPMWYD3NJA:#?}`",
432 $("\n", $fmt_literal, "\n")?
433 ),
434 $($($fmt_arg,)*)?
435 left_NHPMWYD3NJA = $left,
436 right_NHPMWYD3NJA = $right
437 )
438 }
439 };
440 }
441}