const_format/macros/assertions/
assertcp_macros.rs

1macro_rules! with_shared_docs {(
2    $(#[$before_clarification:meta])*
3    ;clarification
4    $(#[$before_syntax:meta])*
5    ;syntax
6    $(#[$after_syntax:meta])*
7    ;limitations
8    $item:item
9) => (
10    $(#[$before_clarification])*
11    ///
12    /// [For **examples** look here](#examples)
13    ///
14    /// This macro requires the `"assertcp"` feature to be exported.<br>
15    ///
16    $(#[$before_syntax])*
17    /// # Syntax
18    ///
19    /// This macro uses the same syntax
20    /// for the format string and formatting arguments as the
21    /// [`formatcp`](crate::formatcp) macro.
22    ///
23    $(#[$after_syntax])*
24    /// # Limitations
25    ///
26    /// This macro can only take constants of these types as arguments:
27    ///
28    /// - `&str`
29    ///
30    /// - `i*`/`u*` (all the primitive integer types).
31    ///
32    /// - `char`
33    ///
34    /// - `bool`
35    ///
36    /// This macro also has these limitations:
37    ///
38    /// - It can only use constants that involve concrete types,
39    /// so while a `Type::<u8>::FOO` in an argument would be fine,
40    /// `Type::<T>::FOO` would not be (`T` being a type parameter).
41    ///
42    /// - Integer arguments must have a type inferrable from context,
43    /// [as described in the integer arguments section in the root module
44    /// ](./index.html#integer-args).
45    ///
46    $item
47)}
48
49with_shared_docs! {
50    /// Compile-time assertion with formatting.
51    ///
52    ;clarification
53    ;syntax
54    ;limitations
55    ///
56    /// # Examples
57    ///
58    /// ### Passing assertion
59    ///
60    /// ```rust
61    /// use const_format::assertcp;
62    ///
63    /// use std::mem::align_of;
64    ///
65    /// assertcp!(
66    ///     align_of::<&str>() == align_of::<usize>(),
67    ///     "The alignment of `&str`({} bytes) and `usize`({} bytes) isn't the same?!?!",
68    ///     align_of::<&str>(),
69    ///     align_of::<usize>(),
70    /// );
71    ///
72    /// # fn main(){}
73    /// ```
74    ///
75    /// ### Failing assertion
76    ///
77    /// This example demonstrates a failing assertion,
78    /// and how the compiler error looks like as of 2023-10-14.
79    ///
80    /// ```compile_fail
81    /// use const_format::assertcp;
82    ///
83    /// const L: u64 = 2;
84    /// const R: u32 = 5;
85    ///
86    /// assertcp!(L.pow(R) == 64, "{L} to the {R} isn't 64, it's {}", L.pow(R));
87    ///
88    /// # fn main(){}
89    /// ```
90    ///
91    /// This is the compiler output:
92    ///
93    /// ```text
94    /// error[E0080]: evaluation of constant value failed
95    ///  --> const_format/src/macros/assertions/assertcp_macros.rs:116:11
96    ///   |
97    /// 9 | assertcp!(L.pow(R) == 64, "{L} to the {R} isn't 64, it's {}", L.pow(R));
98    ///   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at '
99    /// assertion failed.
100    /// 2 to the 5 isn't 64, it's 32
101    /// ', const_format/src/macros/assertions/assertcp_macros.rs:9:11
102    ///
103    /// ```
104    ///
105    #[cfg_attr(feature = "__docsrs", doc(cfg(feature = "assertcp")))]
106    #[macro_export]
107    macro_rules! assertcp {
108        ($($parameters:tt)*) => (
109            $crate::__assertc_inner!{
110                __formatcp_if_impl
111                ($($parameters)*)
112                ($($parameters)*)
113            }
114        );
115    }
116}
117
118#[doc(hidden)]
119#[macro_export]
120macro_rules! __assertcp_equality_inner {
121    (
122        ($($parameters:tt)*)
123        (
124            $left:expr,
125            $right:expr
126            $(, $fmt_literal:expr $(,$fmt_arg:expr)*)? $(,)?
127        )
128        ($($op:tt)*)
129        ($op_str:expr)
130    )=>{
131        #[allow(non_snake_case)]
132        const _: () = {
133            use $crate::__cf_osRcTFl4A;
134            const ARGS_NHPMWYD3NJA:
135                ($crate::pmr::bool, $crate::pmr::PArgument, $crate::pmr::PArgument)
136            = {
137                let left = $crate::PWrapper($left);
138                let right = $crate::pmr::PConvWrapper($right);
139                let cond = left.const_eq(&right.0);
140                let fmt = $crate::pmr::FormattingFlags::NEW.set_alternate(true);
141                (
142                    cond,
143                    $crate::pmr::PConvWrapper(left.0).to_pargument_debug(fmt),
144                    right.to_pargument_debug(fmt),
145                )
146            };
147
148            $crate::__assertc_common!{
149                __formatcp_if_impl
150                ($($parameters)*)
151                (ARGS_NHPMWYD3NJA.0 $($op)* true)
152                (
153                    concat!(
154                        "\nassertion failed: `(left ",
155                        $op_str,
156                        " right)`\n",
157                        " left: `{left_NHPMWYD3NJA:#?}`\n\
158                         right: `{right_NHPMWYD3NJA:#?}`",
159                        $("\n", $fmt_literal, "\n")?
160                    ),
161                    $($($fmt_arg,)*)?
162                    left_NHPMWYD3NJA = ARGS_NHPMWYD3NJA.1,
163                    right_NHPMWYD3NJA = ARGS_NHPMWYD3NJA.2
164                )
165            }
166        };
167    }
168}
169
170with_shared_docs! {
171    /// Compile-time equality assertion with formatting.
172    ///
173    ;clarification
174    ;syntax
175    ;limitations
176    ///
177    /// # Examples
178    ///
179    /// ### Passing assertion
180    ///
181    /// ```rust
182    /// use const_format::assertcp_eq;
183    ///
184    /// const NAME: &str = "Bob";
185    ///
186    /// assertcp_eq!(NAME, "Bob", "Guessed wrong, the right value is {}", NAME);
187    ///
188    /// const SUM: u8 = 1 + 2 + 3;
189    /// assertcp_eq!(6u8, SUM, "Guessed wrong, the right value is {}", SUM);
190    /// ```
191    ///
192    /// ### Failing assertion
193    ///
194    /// This example demonstrates a failing assertion,
195    /// and how the compiler error looks like as of 2023-10-14.
196    ///
197    /// ```compile_fail
198    /// use const_format::assertcp_eq;
199    ///
200    /// use std::mem::size_of;
201    ///
202    /// #[repr(C)]
203    /// struct Type(u16, u16, u16);
204    ///
205    /// assertcp_eq!(size_of::<Type>(), size_of::<[u16; 2]>(), "Whoops, `Type` is too large");
206    ///
207    /// ```
208    ///
209    /// This is the compiler output:
210    ///
211    /// ```text
212    /// error[E0080]: evaluation of constant value failed
213    ///   --> const_format/src/macros/assertions/assertcp_macros.rs:235:14
214    ///    |
215    /// 12 | assertcp_eq!(size_of::<Type>(), size_of::<[u16; 2]>(), "Whoops, `Type` is too large");
216    ///    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at '
217    /// assertion failed: `(left == right)`
218    ///  left: `6`
219    /// right: `4`
220    /// Whoops, `Type` is too large
221    /// ', const_format/src/macros/assertions/assertcp_macros.rs:12:14
222    ///
223    /// ```
224    ///
225    #[cfg_attr(feature = "__docsrs", doc(cfg(feature = "assertcp")))]
226    #[macro_export]
227    macro_rules! assertcp_eq {
228        ($($parameters:tt)*) => (
229            $crate::__assertcp_equality_inner!{
230                ($($parameters)*)
231                ($($parameters)*)
232                ( == )
233                ("==")
234            }
235        );
236    }
237}
238with_shared_docs! {
239    /// Compile-time inequality assertion with formatting.
240    ///
241    ;clarification
242    ;syntax
243    ;limitations
244    ///
245    /// # Examples
246    ///
247    /// ### Passing assertion
248    ///
249    /// ```rust
250    /// use const_format::assertcp_ne;
251    ///
252    /// assertcp_ne!(std::mem::size_of::<usize>(), 1usize, "Oh no, usize is tiny!");
253    ///
254    /// const CHAR: char = ';';
255    /// assertcp_ne!(CHAR, '.', "CHAR must not be a dot!");
256    /// ```
257    ///
258    /// ### Failing assertion
259    ///
260    /// This example demonstrates a failing assertion,
261    /// and how the compiler error looks like as of 2023-10-14.
262    ///
263    /// ```compile_fail
264    /// use const_format::assertcp_ne;
265    ///
266    /// const NAME: &str = "";
267    /// assertcp_ne!(NAME, "", "NAME must not be empty!");
268    ///
269    /// ```
270    ///
271    /// This is the compiler output:
272    ///
273    /// ```text
274    /// error[E0080]: evaluation of constant value failed
275    ///  --> const_format/src/macros/assertions/assertcp_macros.rs:297:14
276    ///   |
277    /// 8 | assertcp_ne!(NAME, "", "NAME must not be empty!");
278    ///   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at '
279    /// assertion failed: `(left != right)`
280    ///  left: `""`
281    /// right: `""`
282    /// NAME must not be empty!
283    /// ', const_format/src/macros/assertions/assertcp_macros.rs:8:14
284    /// ```
285    ///
286    #[cfg_attr(feature = "__docsrs", doc(cfg(feature = "assertcp")))]
287    #[macro_export]
288    macro_rules! assertcp_ne {
289        ($($parameters:tt)*) => (
290            $crate::__assertcp_equality_inner!{
291                ($($parameters)*)
292                ($($parameters)*)
293                ( != )
294                ("!=")
295            }
296        );
297    }
298}