claims/
assert_lt.rs

1/// Asserts that the first expression is less than the second.
2///
3/// Requires that both expressions be comparable with `<`.
4///
5/// ## Uses
6///
7/// Assertions are always checked in both debug and release builds, and cannot be disabled.
8/// See [`debug_assert_lt!`] for assertions that are not enabled in release builds by default.
9///
10/// ## Custom messages
11///
12/// This macro has a second form, where a custom panic message can be provided with or without
13/// arguments for formatting. See [`std::fmt`] for syntax for this form.
14///
15/// ## Examples
16///
17/// ```rust
18/// # #[macro_use] extern crate claims;
19/// # fn main() {
20/// assert_lt!(1, 2);
21///
22/// // With a custom message
23/// assert_lt!(4, 5, "Expecting that {} is less than {}", 4, 5);
24/// # }
25/// ```
26///
27/// ```rust,should_panic
28/// # #[macro_use] extern crate claims;
29/// # fn main() {
30/// assert_lt!(5, 5);  // Will panic
31/// assert_lt!(6, 5);
32///
33/// // With a custom message
34/// assert_lt!(6, 5, "Not expecting {} to be less than {}", 6, 5);
35/// # }
36/// ```
37///
38/// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
39/// [`debug_assert_lt!`]: crate::debug_assert_lt!
40#[macro_export]
41macro_rules! assert_lt {
42    ($left:expr, $right:expr $(,)?) => {
43        match (&$left, &$right) {
44            (left_val, right_val) => {
45                if !(*left_val < *right_val) {
46                    // The reborrows below are intentional. Without them, the stack slot for the
47                    // borrow is initialized even before the values are compared, leading to a
48                    // noticeable slow down.
49                    ::core::panic!(r#"assertion failed: `(left < right)`
50    left: `{:?}`,
51    right: `{:?}`"#, &*left_val, &*right_val)
52                }
53            }
54        }
55    };
56    ($left:expr, $right:expr, $($arg:tt)+) => {
57        match (&$left, &$right) {
58            (left_val, right_val) => {
59                if !(*left_val < *right_val) {
60                    // The reborrows below are intentional. Without them, the stack slot for the
61                    // borrow is initialized even before the values are compared, leading to a
62                    // noticeable slow down.
63                    ::core::panic!(r#"assertion failed: `(left < right)`
64    left: `{:?}`,
65    right: `{:?}`: {}"#, &*left_val, &*right_val, ::core::format_args!($($arg)+))
66                }
67            }
68        }
69    };
70}
71
72/// Asserts that the first expression is less than the second on debug builds.
73///
74/// This macro behaves the same as [`assert_lt!`] on debug builds. On release builds it is a no-op.
75#[macro_export]
76macro_rules! debug_assert_lt {
77    ($($arg:tt)*) => {
78        #[cfg(debug_assertions)]
79        $crate::assert_lt!($($arg)*);
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    #[test]
86    #[should_panic(expected = "assertion failed: `(left < right)`\n    left: `5`,\n    right: `3`")]
87    fn greater_than() {
88        assert_lt!(5, 3);
89    }
90
91    #[test]
92    #[should_panic(expected = "assertion failed: `(left < right)`\n    left: `3`,\n    right: `3`")]
93    fn equal() {
94        assert_lt!(3, 3);
95    }
96
97    #[test]
98    fn less_than() {
99        assert_lt!(1, 3);
100    }
101
102    #[test]
103    #[should_panic(
104        expected = "assertion failed: `(left < right)`\n    left: `5`,\n    right: `3`: foo"
105    )]
106    fn greater_than_custom_message() {
107        assert_lt!(5, 3, "foo");
108    }
109
110    #[test]
111    #[should_panic(
112        expected = "assertion failed: `(left < right)`\n    left: `3`,\n    right: `3`: foo"
113    )]
114    fn equal_custom_message() {
115        assert_lt!(3, 3, "foo");
116    }
117
118    #[test]
119    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
120    #[should_panic(expected = "assertion failed: `(left < right)`\n    left: `5`,\n    right: `3`")]
121    fn debug_greater_than() {
122        debug_assert_lt!(5, 3);
123    }
124
125    #[test]
126    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
127    #[should_panic(expected = "assertion failed: `(left < right)`\n    left: `3`,\n    right: `3`")]
128    fn debug_equal() {
129        debug_assert_lt!(3, 3);
130    }
131
132    #[test]
133    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
134    fn debug_less_than() {
135        debug_assert_lt!(1, 3);
136    }
137
138    #[test]
139    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
140    #[should_panic(
141        expected = "assertion failed: `(left < right)`\n    left: `5`,\n    right: `3`: foo"
142    )]
143    fn debug_greater_than_custom_message() {
144        debug_assert_lt!(5, 3, "foo");
145    }
146
147    #[test]
148    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
149    #[should_panic(
150        expected = "assertion failed: `(left < right)`\n    left: `3`,\n    right: `3`: foo"
151    )]
152    fn debug_equal_custom_message() {
153        debug_assert_lt!(3, 3, "foo");
154    }
155
156    #[test]
157    #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
158    fn debug_release_greater_than() {
159        debug_assert_lt!(5, 3);
160    }
161
162    #[test]
163    #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
164    fn debug_release_equal() {
165        debug_assert_lt!(3, 3);
166    }
167}