const_panic/macros/
concat_assert.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/// Asserts that `$condition` is true.
///
/// When only the `$condition` argument is passed,
/// this delegates to the [`core::assert`] macro.
///
/// When two or more arguments are passed,
/// this panics with formatting by delegating the second and remaining arguments
/// to the [`concat_panic`](macro@crate::concat_panic) macro.
///
/// ### Examples
///
/// ### Formatted assertion
///
/// ```compile_fail
/// use const_panic::concat_assert;
///
/// const ONE: Even = Even::new(1);
///
/// struct Even(u32);
///
/// impl Even {
///     #[track_caller]
///     const fn new(n: u32) -> Self {
///         concat_assert!(n % 2 == 0, "\nexpected the argument to be even, found: ", n);
///         
///         Even(n)
///     }
/// }
/// ```
/// the above code errors with this message:
/// ```text
/// error[E0080]: evaluation of constant value failed
///  --> src/macros/concat_assert.rs:16:19
///   |
/// 4 | const ONE: Even = Even::new(1);
///   |                   ^^^^^^^^^^^^ the evaluated program panicked at '
/// expected the argument to be even, found: 1', src/macros/concat_assert.rs:4:19
///
/// ```
///
/// ### More formatting
///
/// This example demonstrates what error non-`#[track_caller]` functions produce,
/// and uses the `"non_basic"` feature(enabled by default).
///
/// ```compile_fail
/// use const_panic::concat_assert;
///
/// const SUM: u64 = sum(&[3, 5, 8], 1..40);
///
/// const fn sum(mut slice: &[u32], range: std::ops::Range<usize>) -> u64 {
///     concat_assert!(
///         range.start <= range.end && range.end <= slice.len(),
///         "\ncannot index slice of length `", slice.len(),
///         "` with `", range, "` range"
///     );
///     
///     let mut sum = 0u64;
///     
///     while let [curr, ref rem @ ..] = *slice {
///         sum += curr as u64;
///         
///         slice = rem;
///     }
///     
///     sum
/// }
/// ```
/// the above code errors with this message:
/// ```text
/// error[E0080]: evaluation of constant value failed
///   --> src/macros/concat_assert.rs:52:5
///    |
/// 6  |   const SUM: u64 = sum(&[3, 5, 8], 1..40);
///    |                    ---------------------- inside `SUM` at src/macros/concat_assert.rs:6:18
/// ...
/// 9  | /     concat_assert!(
/// 10 | |         range.start <= range.end && range.end <= slice.len(),
/// 11 | |         "\ncannot index slice of length `", slice.len(),
/// 12 | |         "` with `", range, "` range"
/// 13 | |     );
///    | |     ^
///    | |     |
///    | |_____the evaluated program panicked at '
/// cannot index slice of length `3` with `1..40` range', src/macros/concat_assert.rs:9:5
///    |       inside `_doctest_main_src_macros_concat_assert_rs_46_0::sum` at /home/matias/Documents/proyectos programacion/const_panic/src/macros.rs:240:21
///    |
///    = note: this error originates in the macro `$crate::concat_panic` (in Nightly builds, run with -Z macro-backtrace for more info)
/// ```
///
/// ### Unformatted assertion
///
/// When only the `$condition` argument is passed,
/// this delegates to the [`core::assert`] macro.
///
/// ```compile_fail
/// use const_panic::concat_assert;
///
/// const _: () = concat_assert!(cfg!(any(feature = "foo", feature = "bar")) );
/// ```
/// the above code errors with this message:
/// ```text
/// error[E0080]: evaluation of constant value failed
///  --> src/macros/concat_assert.rs:48:15
///   |
/// 6 | const _: () = concat_assert!(cfg!(any(feature = "foo", feature = "bar")) );
///   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: cfg!(any(feature = \"foo\", feature = \"bar\"))', src/macros/concat_assert.rs:6:15
///   |
///   = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
/// ```
///
///
#[macro_export]
macro_rules! concat_assert {
    ($condition:expr $(,)?) => {
        $crate::__::assert!($condition);
    };
    ($condition:expr, $($fmt:tt)*) => {{
        #[allow(clippy::equatable_if_let)]
        if let false = $condition {
            $crate::concat_panic!{$($fmt)*}
        }
    }};
}